0

I have 3 JSON web services which I should use in my application, I use $http to load from URL, my code is :

$http.get('http://{url}/users')
    .then(function (result) {
        storeUsers(result);
    });

$http.get('http://{url}/news')
    .then(function (result) {
        storeNews(result);
    });

$http.get('http://{url}/pages')
    .then(function (result) {
        storePages(result);
    });

var users = getUsers();

Problems :

1- all $http run together not wait until the previuse $http done.

2- var users = getUsers(); will run before $http done.

UPDATE : I changed my code to :

 var loadedService = {
            users: false,
            news: false,
            pages: false
        };

function getUsers() {
            deferred = $q.defer();
            $http.get('http://{url}/users')
                .then(function (result) {
                    loadedService.users = result;
                    deferred.resolve('I got users');
                    console.log("Get users");
                });
            return deferred.promise;
        }

function getNews() {
            deferred = $q.defer();
            $http.get('http://{url}/news')
                .then(function (result) {
                    loadedService.news = result;
                    deferred.resolve('I got news');
                    console.log("Get news");
                });
            return deferred.promise;
        }

function getPages() {
            deferred = $q.defer();
            $http.get('http://{url}/pages')
                .then(function (result) {
                    loadedService.pages = result;
                    deferred.resolve('I got pages');
                    console.log("Get pages");
                });
            return deferred.promise;
        }


getNews().then(getUsers()).then(getPages()).then(function () {
     console.log('Done !');
});

When I run my program, I will see :

XHR finished loading: GET "http://{url}/pages". ionic.bundle.js:16185
Get pages sync.js:133
XHR finished loading: GET "http://{url}/users". ionic.bundle.js:16185
Get users sync.js:56
XHR finished loading: GET "http://{url}/news". ionic.bundle.js:16185
Get news sync.js:107

as you can see, first of all pages service loaded, then users service and then news, while in my code I said getNews().then(getUsers()).then(getPages()).

and finally console.log('Done !'); don't show !

2
  • You should use promises, when a http promise is resolved execute the next http request Commented Nov 24, 2014 at 8:23
  • Thanks @Avraam, but how can I use promises ? I'm newbie in AngularJS Commented Nov 24, 2014 at 8:23

6 Answers 6

3

You can use one of the ways MajoB or Muhammad suggested or you can have 3 functions that return promise and chain them in the order that you want.

function getUsers(){
    deferred = $q.defer()

    $http.get('http://{url}/users')
    .success(function (result) {
        storeUsers(result);
        deferred.resolve('I got users')
    }).error(function(data, status, headers, config) {
      // called if an error occurs
      console.log('error');
      deferred.reject(status)
    });

    return deferred.promise
}

function getNews(){
    deferred = $q.defer()

    $http.get('http://{url}/news')
    .success(function (result) {
        storeUsers(result);
        deferred.resolve('I got news')
    }).error(function(data, status, headers, config) {
      // called if an error occurs
      console.log('error');
      deferred.reject(status)
    });

    return deferred.promise
}


function getPages(){
    deferred = $q.defer()

    $http.get('http://{url}/pages')
    .success(function (result) {
        storePages(result);
        deferred.resolve('I got pages')
    }).error(function(data, status, headers, config) {
      // called if an error occurs
      console.log('error');
      deferred.reject(status)
    });;


    return deferred.promise
} 

For example lets say that you want to get the Pages after you get the News:

getNews().then(getPages())

Each even better to reject a promise on an error case and have an error handling on the chaining:

getNews().then(function() {
  console.log('Success');
  getPages();
}, function() {
  console.log('Failed');
}, function() {
  console.log('Executing... ');
});

Ofcourse the chain also returns a promise which you can handle.

Sign up to request clarification or add additional context in comments.

11 Comments

Your solution is correct, because this way code looks much better, but you should also show how OP can chain those promises.
@MarekSadura I updated it, I hope is more clear now.
@Avraam Thanks, I use this way but I get ReferenceError: $q is not defined
@MajAfy you should inject the $q service inside your directive or controller. See dependency injection here docs.angularjs.org/guide/di and the $q service here docs.angularjs.org/api/ng/service/$q . If you have problem update your question with your full code of where you use the $http and I will update my answer.
@Avraam I think this code don't use queue for requesting services, because I load a service in first function which have large size and then load another service after that, when I watch the console in chrome, second service will load first and then first service will load after that(because first service is about 8MB and second service is 120KB)
|
2

you can chain your requests:

       $http.get('http://{url}/users')
        .then(function (result) {
            storeUsers(result);
            $http.get('http://{url}/news')
                .then(function (newsResult) {
                    storeNews(newsResult);
                    $http.get('http://{url}/pages')
                        .then(function (pagesResult) {
                        storePages(pagesResult);
                    });
                });
        });

Comments

2

You can make $http requests run after each other by putting the code inside the success promise.

var users; // declare `users` variable
$http.get('http://{url}/users')
    .then(function (result) {
        storeUsers(result);

        // second ajax request
        $http.get('http://{url}/news')
            .then(function (result) {
                storeNews(result);
                // third ajax request goes here
                // .....


                // set the value for users
                users = getUsers();
            });
    });

1 Comment

Thanks, It came to my mind but is it logical and true ?
1

here a little testScript for using promises with angularJs

$scope.myXhr = function(){

var deferred = $q.defer();

$http({
    url: 'ajax.php',
    method: "POST",
    data:postData,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    })
    //if request is successful
    .success(function(data,status,headers,config){

        //resolve the promise
        deferred.resolve("request successful");

    })
    //if request is not successful
    .error(function(data,status,headers,config){
        //reject the promise
        deferred.reject("ERROR");
    });

//return the promise
return deferred.promise;
}

$scope.callXhrAsynchronous = function(){

var myPromise = $scope.myXhr();

// wait until the promise return resolve or eject
//"then" has 2 functions (resolveFunction, rejectFunction)
myPromise.then(function(resolve){
    alert(resolve);
    }, function(reject){
    alert(reject)      
});

}

Comments

1

You can try this:

NoticeService.observeReqUser().then(null,null,function(){
    $http.get('http://{url}/users')
        .then(function (result) {
            storeUsers(result);
            NoticeService.notifyStatusOne()
        });
});

NoticeService.observeReqOne().then(null,null,function(){
    $http.get('http://{url}/news')
        .then(function (result) {
            storeNews(result);
            NoticeService.notifyStatusTwo()
        });
});

NoticeService.observeReqTwo().then(null,null,function(){
    $http.get('http://{url}/pages')
        .then(function (result) {
            storePages(result);
        });
});

var users = getUsers();

You need to create a service to notify the request is done so the next one can be called

app.service('NoticeService',['$q',function($q){
    var noticegetUserIsDone = $q.defer();

    this.observeReqUser = function() { return noticegetUserIsDone.promise; };
    this.notifyStatusUser = function() { noticegetUserIsDone.notify(); };

    var noticeReqOneIsDone = $q.defer();
    this.observeReqOne = function() { return noticegetUserIsDone.promise; };
    this.notifyStatusOne = function() { noticegetUserIsDone.notify(); };

    var noticeReqTwoIsDone = $q.defer();
    this.observeReqTwo = function() { return noticegetUserIsDone.promise; };
    this.notifyStatusTwo = function() { noticegetUserIsDone.notify(); };
};

You will need to call the NoticeService.notifyStatusUser from the end of getUser function so the chain will start to execute (Don't forget to add reference of the NoticeService where you call it)

Comments

1

You can use something like this, if I understand your question correctly:

$http.get('http://{url}/users')
  .then(function (result) {
    storeUsers(result);

    return $http.get('http://{url}/news');
  })
  .then(function (result) {
    storeNews(result);

    return $http.get('http://{url}/pages');
  })
  .then(function (result) {
    storePages(result);

    users = getUsers();
  });

$http.get will return promise.

Updated:

Or more clean solution:

var deferred = $q.defer(),
    users;

$http.get('http://{url}/users')
  .then(function (result) {
    storeUsers(result);

    return $http.get('http://{url}/news');
  })
  .then(function (result) {
    storeNews(result);

    return $http.get('http://{url}/pages');
  })
  .then(function (result) {
    storePages(result);

    deferred.resolve(result);
  });

 deferred.promise.then(function() {
   users = getUsers();
 });

Update2:

or more simple:

var request1 = $http.get('http://{url}/users'),
    request2 = $http.get('http://{url}/news'),
    request3 = $http.get('http://{url}/pages');

$q.all([request1, request2, request3]).then(function(result) {
  storeUsers(result[0]);
  storeNews(result[1]);
  storePages(result[2]);

  users = getUsers();
}

But you also need to handle rejection case.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.