1

I want to call the api after completing the first is success.But in my code it call the api before the first one was completed

  for(var w=0;w<Ids.length;w++){
      $scope.msgObject = {
               "SenderID":$scope.pageId,
               "PageID" : $scope.pageId,
                "Date":Date.now().toString(),
              };

        $http({
            method: 'POST',
           url: '///url',
           async:true,
            data: $scope.msgObject,
            headers: {
                'Content-Type': 'application/json'
            }})
            .then(function(response) {
              console.log("success posting");
              }
            })
             .catch(function(response){

            });
      $(".messageInput").val('');


      }
    }
  }
}
kragor
  • 105
  • 2
  • 11
  • 2
    Would you clarify your question? Each iteration of your loop will fire an asynchronous API call to your URL, and the loop will not wait for each response. The code in each of your then() functions will run (asynchronously) as the responses return. Is this what you are expecting? (edited - spelling) – Karl Wenzel Dec 13 '16 at 21:23
  • I think this is what you're looking for: http://stackoverflow.com/a/33741475/5547718. In your case, you have to dynnamically create the myAsynchFunctions array by simply pushing the ajax request. – ThatBrianDude Dec 13 '16 at 21:23
  • this question is a dupe. you will find the answer on google. this question is identical to like 60% of the other questions in the javascript tab. – I wrestled a bear once. Dec 13 '16 at 21:26
  • @KarlWenzel I want the loop to wait for the response and go to next iteration after receiving the response of first call – kragor Dec 13 '16 at 21:27
  • If you want the loop to wait, then you should not use async: true, however this function would then block JS execution in the meantime. Some of the other comments offered seem to offer a better strategy. – Karl Wenzel Dec 13 '16 at 21:31
  • "sync" AJAX calls are not recommended at all (also, deprecated e.g. in Chrome) – Ben Bracha Dec 13 '16 at 21:51

4 Answers4

4

function asyncForEach(arr, cb) {
    return arr.reduce((p,c)=>{
        return p.then(()=> cb(c));
    }, Promise.resolve());
}

function fetch(id) {
  return new Promise(resolve=>
    setTimeout(resolve, 100)) // replace with your AJAX call
      .then(()=>console.log('success posting', id));
}

function done() {
    console.log('all done!');
}

const ids = [1, 2, 3, 4, 5];
asyncForEach(ids, fetch).then(done);
Ben Aston
  • 53,718
  • 65
  • 205
  • 331
0

put your loop inside THEN something like

function urPostMethod(url){

$scope.msgObject = {
               "SenderID":$scope.pageId,
               "PageID" : $scope.pageId,
                "Date":Date.now().toString(),
              };

        $http({
            method: 'POST',
           url: url,
           async:true,
            data: $scope.msgObject,
            headers: {
                'Content-Type': 'application/json'
            }})
            .then(function(response) {
              console.log("success posting");
              while(Ids.length>0)urPostMethod(Ids.pop());
              }
            })
             .catch(function(response){

            });
      $(".messageInput").val('');


      }
    }
  }
}
0

What you are trying to do is to mix async and sync operations together which is not logical at all.

If you need to call those API's in order of your elements in your array, you may use a different approach like pipe the requests using Defer:

var dfd = $.Deferred(),  
    x = 0, // Loop index
    Ids = [],
    msgObject = {
       "SenderID":$scope.pageId,
       "PageID" : $scope.pageId,
        "Date":Date.now().toString(),
      };


    callAjax = function (value) {
        var dfdAjax = $.Deferred();

        $.ajax({
            method: 'POST',
            url: '///url',
            async:true,
            data: msgObject,
            headers: {
                'Content-Type': 'application/json'
            }})
        .then(function(response) {
           dfdAjax.resolve(response);
        })
        .catch(function(response){
            dfdAjax.reject(response);
        });        

        return dfdAjax.promise();
    },

    requestAjax = function (value) {
        return callAjax(value);
    };

dfd.resolve();

for (x = 1; x <= Ids.length; x++) {

    dfdNext = dfdNext.pipe(function () {        
        return requestAjax(value).
            done(function(response) {
                // Process the response here.
            });

    });

}
Yaser
  • 5,609
  • 1
  • 15
  • 27
0

You could use $q.all() and simplify your syntax, you'll just need to inject the $q service.

The below code adds all the promises returned by $http into a single array, executes the promises using $q.all() and then gathers their results.

var requests = [];

for(var w = 0; w < Ids.length; w++) {    
    var req = $http({
        method: 'POST',
        url: '///url',
        headers: { 'Content-Type': 'application/json' },
        data: {
          SenderID: $scope.pageId,
          PageID: $scope.pageId,
          Date: Date.now().toString(),
        }
    })
        .catch(function(err) {
            // handle err 
        });

    requests.push(req);
}

$q.all(requests)
    .then(function (results) {
        // handle results
    });;
peteb
  • 18,552
  • 9
  • 50
  • 62