How to make a forEach loop wait for each Ajax function to finish












2














I have an array of statements and I want to loop through each and submit to the server via an ajax call. I have to make sure each ajax request is executed before the next request is sent, because on the server side code, I am creating a unique key for this array of statements. What happens is before I can commit the first request, the second request comes in and I end up have 2 separate keys being created since it sees each of them as a first time request. I can't rely on timeout entirely and the code I have so far, continues with the loop.



function formPostSubmission(form){
var parts = ['a', 'b', 'c'];
var i = 0;
parts.forEach(function(entry) {
i++;
datafield ={
answer:entry,
displayOrder:i,
ajaxName:'statementPartialSubmit'
};
$.when(submitAjaxData(form, datafield)).then(function succesHandler(data){
console.log("promise test "+data);
console.log("Below request ");
},
function errorHandler(){
console.log("Error occurred ");
})
console.log("Go for next ");
});
}

function submitAjaxData(form, datafield) {
console.log(" called submitAjaxData ");
var loadurl = domainName + "/ajax-call-handler";
return $.ajax({
url: loadurl,
method: "GET",
data: datafield
});
}


I was hoping to check response data for a success and then proceed within the loop. But this is how my console prints.



called submitAjaxData
Go for next
called submitAjaxData
Go for next
promise test
Below request
promise test
Below request









share|improve this question
























  • Your post is tagged with java, but should be tagged with javascript instead. Remember, those are completely different things.
    – Fitzi
    Nov 13 '18 at 8:40
















2














I have an array of statements and I want to loop through each and submit to the server via an ajax call. I have to make sure each ajax request is executed before the next request is sent, because on the server side code, I am creating a unique key for this array of statements. What happens is before I can commit the first request, the second request comes in and I end up have 2 separate keys being created since it sees each of them as a first time request. I can't rely on timeout entirely and the code I have so far, continues with the loop.



function formPostSubmission(form){
var parts = ['a', 'b', 'c'];
var i = 0;
parts.forEach(function(entry) {
i++;
datafield ={
answer:entry,
displayOrder:i,
ajaxName:'statementPartialSubmit'
};
$.when(submitAjaxData(form, datafield)).then(function succesHandler(data){
console.log("promise test "+data);
console.log("Below request ");
},
function errorHandler(){
console.log("Error occurred ");
})
console.log("Go for next ");
});
}

function submitAjaxData(form, datafield) {
console.log(" called submitAjaxData ");
var loadurl = domainName + "/ajax-call-handler";
return $.ajax({
url: loadurl,
method: "GET",
data: datafield
});
}


I was hoping to check response data for a success and then proceed within the loop. But this is how my console prints.



called submitAjaxData
Go for next
called submitAjaxData
Go for next
promise test
Below request
promise test
Below request









share|improve this question
























  • Your post is tagged with java, but should be tagged with javascript instead. Remember, those are completely different things.
    – Fitzi
    Nov 13 '18 at 8:40














2












2








2







I have an array of statements and I want to loop through each and submit to the server via an ajax call. I have to make sure each ajax request is executed before the next request is sent, because on the server side code, I am creating a unique key for this array of statements. What happens is before I can commit the first request, the second request comes in and I end up have 2 separate keys being created since it sees each of them as a first time request. I can't rely on timeout entirely and the code I have so far, continues with the loop.



function formPostSubmission(form){
var parts = ['a', 'b', 'c'];
var i = 0;
parts.forEach(function(entry) {
i++;
datafield ={
answer:entry,
displayOrder:i,
ajaxName:'statementPartialSubmit'
};
$.when(submitAjaxData(form, datafield)).then(function succesHandler(data){
console.log("promise test "+data);
console.log("Below request ");
},
function errorHandler(){
console.log("Error occurred ");
})
console.log("Go for next ");
});
}

function submitAjaxData(form, datafield) {
console.log(" called submitAjaxData ");
var loadurl = domainName + "/ajax-call-handler";
return $.ajax({
url: loadurl,
method: "GET",
data: datafield
});
}


I was hoping to check response data for a success and then proceed within the loop. But this is how my console prints.



called submitAjaxData
Go for next
called submitAjaxData
Go for next
promise test
Below request
promise test
Below request









share|improve this question















I have an array of statements and I want to loop through each and submit to the server via an ajax call. I have to make sure each ajax request is executed before the next request is sent, because on the server side code, I am creating a unique key for this array of statements. What happens is before I can commit the first request, the second request comes in and I end up have 2 separate keys being created since it sees each of them as a first time request. I can't rely on timeout entirely and the code I have so far, continues with the loop.



function formPostSubmission(form){
var parts = ['a', 'b', 'c'];
var i = 0;
parts.forEach(function(entry) {
i++;
datafield ={
answer:entry,
displayOrder:i,
ajaxName:'statementPartialSubmit'
};
$.when(submitAjaxData(form, datafield)).then(function succesHandler(data){
console.log("promise test "+data);
console.log("Below request ");
},
function errorHandler(){
console.log("Error occurred ");
})
console.log("Go for next ");
});
}

function submitAjaxData(form, datafield) {
console.log(" called submitAjaxData ");
var loadurl = domainName + "/ajax-call-handler";
return $.ajax({
url: loadurl,
method: "GET",
data: datafield
});
}


I was hoping to check response data for a success and then proceed within the loop. But this is how my console prints.



called submitAjaxData
Go for next
called submitAjaxData
Go for next
promise test
Below request
promise test
Below request






javascript jquery ajax loops






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 20:46









Udi

17.7k46792




17.7k46792










asked Nov 13 '18 at 6:41









RacheRache

146214




146214












  • Your post is tagged with java, but should be tagged with javascript instead. Remember, those are completely different things.
    – Fitzi
    Nov 13 '18 at 8:40


















  • Your post is tagged with java, but should be tagged with javascript instead. Remember, those are completely different things.
    – Fitzi
    Nov 13 '18 at 8:40
















Your post is tagged with java, but should be tagged with javascript instead. Remember, those are completely different things.
– Fitzi
Nov 13 '18 at 8:40




Your post is tagged with java, but should be tagged with javascript instead. Remember, those are completely different things.
– Fitzi
Nov 13 '18 at 8:40












4 Answers
4






active

oldest

votes


















2














use promises :



 var promises = ;
for (var i = 0; i < $total_files; i++) {
// jQuery returns a prom
promises.push($.ajax({
/* your ajax config*/
}))
}

Promise.all(promises)
.then(responseList => {
console.dir(responseList)
})





share|improve this answer





















  • exact right way to do it
    – Ayeshmantha Perera
    Nov 13 '18 at 6:48










  • Thanks for replying Sari. I just tried this. Can you explain how this is supposed to work. I see that the loop gets the first element and then prints the console message right after the ajax call. But I added a time param to the ajax request and I see the same time added for both the request.
    – Rache
    Nov 13 '18 at 7:12










  • This does not guarantee that the requests are sent sequentially!
    – Fitzi
    Nov 13 '18 at 8:37










  • Yes, I did some more tests and it isn't sent sequentially.
    – Rache
    Nov 13 '18 at 9:23










  • Promise.all just returns all resolved promises at once, or fails if one promise gets rejected. As @Fitzi said, it does not guarantee that they will be solved sequentially
    – darklightcode
    Nov 13 '18 at 20:59



















0














you could use this solution by using await , for example :



for (let f of files) {
await $.ajax({/* your ajax config*/ });
}





share|improve this answer





























    0














    I wrote this function, PromiseAllSeq, to execute an array of promises sequentially.



    You can pass a callback as the second parameter if you choose, but given your issue i've put together a working demo based on your code.






    console.clear();
    /**
    * Promises will wait for each other and will return any.
    * If a promise is rejected it will stop.
    * @param arr - (Promise<any> | ()=>Promise<any>) - Accepts promise or a function that returns a promise
    * @param callback(response, index) - If callback 'returns' it will overwrite the current response. Useful for changing the response.
    * @returns any
    */
    const PromiseAllSeq = (arr, callback) => {

    let result = ;

    if (typeof callback !== 'function') {
    callback = () => {};
    }

    const rec = (arr) => {

    return new Promise((resolve, reject) => {

    if (arr.length) {

    (typeof arr[0] === 'function' ? arr[0]() : arr[0]).then(res => {

    let cb = callback(res, result.length);

    result = result.concat(typeof cb !== 'undefined' ? cb : res);

    arr.splice(0, 1);

    resolve(arr.length ? rec(arr) : result);

    }).catch(err => {

    reject(err);

    })

    } else {

    resolve(result);

    }

    })

    }

    return rec(arr);

    }

    function succesHandler(data, index) {

    // Here i can alter 'data'
    data['finishedPromiseNr'] = index;

    console.log("promise test ", data, index);

    console.log("Go for next ");

    return data;

    }

    function errorHandler(err) {
    console.log("Error occurred ", err);
    }

    function submitAjaxData(form, datafield) {
    console.log("called submitAjaxData ", datafield);
    //var loadurl = domainName + "/ajax-call-handler";

    // Mock some requests with delayed responses
    // https://reqres.in/#console
    var loadurl = "https://reqres.in/api/users?delay=" + datafield.fakeDelay;
    return $.ajax({
    url: loadurl,
    method: "GET",
    data: datafield
    });
    }

    function formPostSubmission(form) {
    var parts = ['a', 'b', 'c'];
    var i = 0;
    let poll = ;
    parts.forEach(function(entry) {
    i++;

    // 'datafield' was not assigned with var or let
    // Reassigning it on each loop will allow 'datafield' to pass in the anonymous function below
    let datafield = {
    answer: entry,
    displayOrder: i,
    ajaxName: 'statementPartialSubmit',
    fakeDelay: parts.length - i
    };

    // Wrong: submitAjaxData is called, that means, the requests are sent immediately.
    // poll.push( $.when(submitAjaxData(form, datafield) );

    // Correct: Wrap and return $.when into a function otherwise 'submitAjaxData' will trigger the requests
    poll.push(() => $.when(submitAjaxData(form, datafield)));

    });

    PromiseAllSeq(poll, succesHandler).then(responseList => {

    console.log('final response');
    console.log(responseList);

    }).catch(errorHandler)


    }

    formPostSubmission(null);

    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>








    share|improve this answer





























      -1














      async: false 


      is the best option in your case






      share|improve this answer

















      • 1




        While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
        – Clijsters
        Nov 13 '18 at 12:29










      • async: false was deprecated years ago because of negative user experience.
        – Tyler Roper
        Nov 13 '18 at 23:58













      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53275216%2fhow-to-make-a-foreach-loop-wait-for-each-ajax-function-to-finish%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      use promises :



       var promises = ;
      for (var i = 0; i < $total_files; i++) {
      // jQuery returns a prom
      promises.push($.ajax({
      /* your ajax config*/
      }))
      }

      Promise.all(promises)
      .then(responseList => {
      console.dir(responseList)
      })





      share|improve this answer





















      • exact right way to do it
        – Ayeshmantha Perera
        Nov 13 '18 at 6:48










      • Thanks for replying Sari. I just tried this. Can you explain how this is supposed to work. I see that the loop gets the first element and then prints the console message right after the ajax call. But I added a time param to the ajax request and I see the same time added for both the request.
        – Rache
        Nov 13 '18 at 7:12










      • This does not guarantee that the requests are sent sequentially!
        – Fitzi
        Nov 13 '18 at 8:37










      • Yes, I did some more tests and it isn't sent sequentially.
        – Rache
        Nov 13 '18 at 9:23










      • Promise.all just returns all resolved promises at once, or fails if one promise gets rejected. As @Fitzi said, it does not guarantee that they will be solved sequentially
        – darklightcode
        Nov 13 '18 at 20:59
















      2














      use promises :



       var promises = ;
      for (var i = 0; i < $total_files; i++) {
      // jQuery returns a prom
      promises.push($.ajax({
      /* your ajax config*/
      }))
      }

      Promise.all(promises)
      .then(responseList => {
      console.dir(responseList)
      })





      share|improve this answer





















      • exact right way to do it
        – Ayeshmantha Perera
        Nov 13 '18 at 6:48










      • Thanks for replying Sari. I just tried this. Can you explain how this is supposed to work. I see that the loop gets the first element and then prints the console message right after the ajax call. But I added a time param to the ajax request and I see the same time added for both the request.
        – Rache
        Nov 13 '18 at 7:12










      • This does not guarantee that the requests are sent sequentially!
        – Fitzi
        Nov 13 '18 at 8:37










      • Yes, I did some more tests and it isn't sent sequentially.
        – Rache
        Nov 13 '18 at 9:23










      • Promise.all just returns all resolved promises at once, or fails if one promise gets rejected. As @Fitzi said, it does not guarantee that they will be solved sequentially
        – darklightcode
        Nov 13 '18 at 20:59














      2












      2








      2






      use promises :



       var promises = ;
      for (var i = 0; i < $total_files; i++) {
      // jQuery returns a prom
      promises.push($.ajax({
      /* your ajax config*/
      }))
      }

      Promise.all(promises)
      .then(responseList => {
      console.dir(responseList)
      })





      share|improve this answer












      use promises :



       var promises = ;
      for (var i = 0; i < $total_files; i++) {
      // jQuery returns a prom
      promises.push($.ajax({
      /* your ajax config*/
      }))
      }

      Promise.all(promises)
      .then(responseList => {
      console.dir(responseList)
      })






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Nov 13 '18 at 6:44









      Sari MasriSari Masri

      1297




      1297












      • exact right way to do it
        – Ayeshmantha Perera
        Nov 13 '18 at 6:48










      • Thanks for replying Sari. I just tried this. Can you explain how this is supposed to work. I see that the loop gets the first element and then prints the console message right after the ajax call. But I added a time param to the ajax request and I see the same time added for both the request.
        – Rache
        Nov 13 '18 at 7:12










      • This does not guarantee that the requests are sent sequentially!
        – Fitzi
        Nov 13 '18 at 8:37










      • Yes, I did some more tests and it isn't sent sequentially.
        – Rache
        Nov 13 '18 at 9:23










      • Promise.all just returns all resolved promises at once, or fails if one promise gets rejected. As @Fitzi said, it does not guarantee that they will be solved sequentially
        – darklightcode
        Nov 13 '18 at 20:59


















      • exact right way to do it
        – Ayeshmantha Perera
        Nov 13 '18 at 6:48










      • Thanks for replying Sari. I just tried this. Can you explain how this is supposed to work. I see that the loop gets the first element and then prints the console message right after the ajax call. But I added a time param to the ajax request and I see the same time added for both the request.
        – Rache
        Nov 13 '18 at 7:12










      • This does not guarantee that the requests are sent sequentially!
        – Fitzi
        Nov 13 '18 at 8:37










      • Yes, I did some more tests and it isn't sent sequentially.
        – Rache
        Nov 13 '18 at 9:23










      • Promise.all just returns all resolved promises at once, or fails if one promise gets rejected. As @Fitzi said, it does not guarantee that they will be solved sequentially
        – darklightcode
        Nov 13 '18 at 20:59
















      exact right way to do it
      – Ayeshmantha Perera
      Nov 13 '18 at 6:48




      exact right way to do it
      – Ayeshmantha Perera
      Nov 13 '18 at 6:48












      Thanks for replying Sari. I just tried this. Can you explain how this is supposed to work. I see that the loop gets the first element and then prints the console message right after the ajax call. But I added a time param to the ajax request and I see the same time added for both the request.
      – Rache
      Nov 13 '18 at 7:12




      Thanks for replying Sari. I just tried this. Can you explain how this is supposed to work. I see that the loop gets the first element and then prints the console message right after the ajax call. But I added a time param to the ajax request and I see the same time added for both the request.
      – Rache
      Nov 13 '18 at 7:12












      This does not guarantee that the requests are sent sequentially!
      – Fitzi
      Nov 13 '18 at 8:37




      This does not guarantee that the requests are sent sequentially!
      – Fitzi
      Nov 13 '18 at 8:37












      Yes, I did some more tests and it isn't sent sequentially.
      – Rache
      Nov 13 '18 at 9:23




      Yes, I did some more tests and it isn't sent sequentially.
      – Rache
      Nov 13 '18 at 9:23












      Promise.all just returns all resolved promises at once, or fails if one promise gets rejected. As @Fitzi said, it does not guarantee that they will be solved sequentially
      – darklightcode
      Nov 13 '18 at 20:59




      Promise.all just returns all resolved promises at once, or fails if one promise gets rejected. As @Fitzi said, it does not guarantee that they will be solved sequentially
      – darklightcode
      Nov 13 '18 at 20:59













      0














      you could use this solution by using await , for example :



      for (let f of files) {
      await $.ajax({/* your ajax config*/ });
      }





      share|improve this answer


























        0














        you could use this solution by using await , for example :



        for (let f of files) {
        await $.ajax({/* your ajax config*/ });
        }





        share|improve this answer
























          0












          0








          0






          you could use this solution by using await , for example :



          for (let f of files) {
          await $.ajax({/* your ajax config*/ });
          }





          share|improve this answer












          you could use this solution by using await , for example :



          for (let f of files) {
          await $.ajax({/* your ajax config*/ });
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 13 '18 at 21:27









          Sari MasriSari Masri

          1297




          1297























              0














              I wrote this function, PromiseAllSeq, to execute an array of promises sequentially.



              You can pass a callback as the second parameter if you choose, but given your issue i've put together a working demo based on your code.






              console.clear();
              /**
              * Promises will wait for each other and will return any.
              * If a promise is rejected it will stop.
              * @param arr - (Promise<any> | ()=>Promise<any>) - Accepts promise or a function that returns a promise
              * @param callback(response, index) - If callback 'returns' it will overwrite the current response. Useful for changing the response.
              * @returns any
              */
              const PromiseAllSeq = (arr, callback) => {

              let result = ;

              if (typeof callback !== 'function') {
              callback = () => {};
              }

              const rec = (arr) => {

              return new Promise((resolve, reject) => {

              if (arr.length) {

              (typeof arr[0] === 'function' ? arr[0]() : arr[0]).then(res => {

              let cb = callback(res, result.length);

              result = result.concat(typeof cb !== 'undefined' ? cb : res);

              arr.splice(0, 1);

              resolve(arr.length ? rec(arr) : result);

              }).catch(err => {

              reject(err);

              })

              } else {

              resolve(result);

              }

              })

              }

              return rec(arr);

              }

              function succesHandler(data, index) {

              // Here i can alter 'data'
              data['finishedPromiseNr'] = index;

              console.log("promise test ", data, index);

              console.log("Go for next ");

              return data;

              }

              function errorHandler(err) {
              console.log("Error occurred ", err);
              }

              function submitAjaxData(form, datafield) {
              console.log("called submitAjaxData ", datafield);
              //var loadurl = domainName + "/ajax-call-handler";

              // Mock some requests with delayed responses
              // https://reqres.in/#console
              var loadurl = "https://reqres.in/api/users?delay=" + datafield.fakeDelay;
              return $.ajax({
              url: loadurl,
              method: "GET",
              data: datafield
              });
              }

              function formPostSubmission(form) {
              var parts = ['a', 'b', 'c'];
              var i = 0;
              let poll = ;
              parts.forEach(function(entry) {
              i++;

              // 'datafield' was not assigned with var or let
              // Reassigning it on each loop will allow 'datafield' to pass in the anonymous function below
              let datafield = {
              answer: entry,
              displayOrder: i,
              ajaxName: 'statementPartialSubmit',
              fakeDelay: parts.length - i
              };

              // Wrong: submitAjaxData is called, that means, the requests are sent immediately.
              // poll.push( $.when(submitAjaxData(form, datafield) );

              // Correct: Wrap and return $.when into a function otherwise 'submitAjaxData' will trigger the requests
              poll.push(() => $.when(submitAjaxData(form, datafield)));

              });

              PromiseAllSeq(poll, succesHandler).then(responseList => {

              console.log('final response');
              console.log(responseList);

              }).catch(errorHandler)


              }

              formPostSubmission(null);

              <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>








              share|improve this answer


























                0














                I wrote this function, PromiseAllSeq, to execute an array of promises sequentially.



                You can pass a callback as the second parameter if you choose, but given your issue i've put together a working demo based on your code.






                console.clear();
                /**
                * Promises will wait for each other and will return any.
                * If a promise is rejected it will stop.
                * @param arr - (Promise<any> | ()=>Promise<any>) - Accepts promise or a function that returns a promise
                * @param callback(response, index) - If callback 'returns' it will overwrite the current response. Useful for changing the response.
                * @returns any
                */
                const PromiseAllSeq = (arr, callback) => {

                let result = ;

                if (typeof callback !== 'function') {
                callback = () => {};
                }

                const rec = (arr) => {

                return new Promise((resolve, reject) => {

                if (arr.length) {

                (typeof arr[0] === 'function' ? arr[0]() : arr[0]).then(res => {

                let cb = callback(res, result.length);

                result = result.concat(typeof cb !== 'undefined' ? cb : res);

                arr.splice(0, 1);

                resolve(arr.length ? rec(arr) : result);

                }).catch(err => {

                reject(err);

                })

                } else {

                resolve(result);

                }

                })

                }

                return rec(arr);

                }

                function succesHandler(data, index) {

                // Here i can alter 'data'
                data['finishedPromiseNr'] = index;

                console.log("promise test ", data, index);

                console.log("Go for next ");

                return data;

                }

                function errorHandler(err) {
                console.log("Error occurred ", err);
                }

                function submitAjaxData(form, datafield) {
                console.log("called submitAjaxData ", datafield);
                //var loadurl = domainName + "/ajax-call-handler";

                // Mock some requests with delayed responses
                // https://reqres.in/#console
                var loadurl = "https://reqres.in/api/users?delay=" + datafield.fakeDelay;
                return $.ajax({
                url: loadurl,
                method: "GET",
                data: datafield
                });
                }

                function formPostSubmission(form) {
                var parts = ['a', 'b', 'c'];
                var i = 0;
                let poll = ;
                parts.forEach(function(entry) {
                i++;

                // 'datafield' was not assigned with var or let
                // Reassigning it on each loop will allow 'datafield' to pass in the anonymous function below
                let datafield = {
                answer: entry,
                displayOrder: i,
                ajaxName: 'statementPartialSubmit',
                fakeDelay: parts.length - i
                };

                // Wrong: submitAjaxData is called, that means, the requests are sent immediately.
                // poll.push( $.when(submitAjaxData(form, datafield) );

                // Correct: Wrap and return $.when into a function otherwise 'submitAjaxData' will trigger the requests
                poll.push(() => $.when(submitAjaxData(form, datafield)));

                });

                PromiseAllSeq(poll, succesHandler).then(responseList => {

                console.log('final response');
                console.log(responseList);

                }).catch(errorHandler)


                }

                formPostSubmission(null);

                <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>








                share|improve this answer
























                  0












                  0








                  0






                  I wrote this function, PromiseAllSeq, to execute an array of promises sequentially.



                  You can pass a callback as the second parameter if you choose, but given your issue i've put together a working demo based on your code.






                  console.clear();
                  /**
                  * Promises will wait for each other and will return any.
                  * If a promise is rejected it will stop.
                  * @param arr - (Promise<any> | ()=>Promise<any>) - Accepts promise or a function that returns a promise
                  * @param callback(response, index) - If callback 'returns' it will overwrite the current response. Useful for changing the response.
                  * @returns any
                  */
                  const PromiseAllSeq = (arr, callback) => {

                  let result = ;

                  if (typeof callback !== 'function') {
                  callback = () => {};
                  }

                  const rec = (arr) => {

                  return new Promise((resolve, reject) => {

                  if (arr.length) {

                  (typeof arr[0] === 'function' ? arr[0]() : arr[0]).then(res => {

                  let cb = callback(res, result.length);

                  result = result.concat(typeof cb !== 'undefined' ? cb : res);

                  arr.splice(0, 1);

                  resolve(arr.length ? rec(arr) : result);

                  }).catch(err => {

                  reject(err);

                  })

                  } else {

                  resolve(result);

                  }

                  })

                  }

                  return rec(arr);

                  }

                  function succesHandler(data, index) {

                  // Here i can alter 'data'
                  data['finishedPromiseNr'] = index;

                  console.log("promise test ", data, index);

                  console.log("Go for next ");

                  return data;

                  }

                  function errorHandler(err) {
                  console.log("Error occurred ", err);
                  }

                  function submitAjaxData(form, datafield) {
                  console.log("called submitAjaxData ", datafield);
                  //var loadurl = domainName + "/ajax-call-handler";

                  // Mock some requests with delayed responses
                  // https://reqres.in/#console
                  var loadurl = "https://reqres.in/api/users?delay=" + datafield.fakeDelay;
                  return $.ajax({
                  url: loadurl,
                  method: "GET",
                  data: datafield
                  });
                  }

                  function formPostSubmission(form) {
                  var parts = ['a', 'b', 'c'];
                  var i = 0;
                  let poll = ;
                  parts.forEach(function(entry) {
                  i++;

                  // 'datafield' was not assigned with var or let
                  // Reassigning it on each loop will allow 'datafield' to pass in the anonymous function below
                  let datafield = {
                  answer: entry,
                  displayOrder: i,
                  ajaxName: 'statementPartialSubmit',
                  fakeDelay: parts.length - i
                  };

                  // Wrong: submitAjaxData is called, that means, the requests are sent immediately.
                  // poll.push( $.when(submitAjaxData(form, datafield) );

                  // Correct: Wrap and return $.when into a function otherwise 'submitAjaxData' will trigger the requests
                  poll.push(() => $.when(submitAjaxData(form, datafield)));

                  });

                  PromiseAllSeq(poll, succesHandler).then(responseList => {

                  console.log('final response');
                  console.log(responseList);

                  }).catch(errorHandler)


                  }

                  formPostSubmission(null);

                  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>








                  share|improve this answer












                  I wrote this function, PromiseAllSeq, to execute an array of promises sequentially.



                  You can pass a callback as the second parameter if you choose, but given your issue i've put together a working demo based on your code.






                  console.clear();
                  /**
                  * Promises will wait for each other and will return any.
                  * If a promise is rejected it will stop.
                  * @param arr - (Promise<any> | ()=>Promise<any>) - Accepts promise or a function that returns a promise
                  * @param callback(response, index) - If callback 'returns' it will overwrite the current response. Useful for changing the response.
                  * @returns any
                  */
                  const PromiseAllSeq = (arr, callback) => {

                  let result = ;

                  if (typeof callback !== 'function') {
                  callback = () => {};
                  }

                  const rec = (arr) => {

                  return new Promise((resolve, reject) => {

                  if (arr.length) {

                  (typeof arr[0] === 'function' ? arr[0]() : arr[0]).then(res => {

                  let cb = callback(res, result.length);

                  result = result.concat(typeof cb !== 'undefined' ? cb : res);

                  arr.splice(0, 1);

                  resolve(arr.length ? rec(arr) : result);

                  }).catch(err => {

                  reject(err);

                  })

                  } else {

                  resolve(result);

                  }

                  })

                  }

                  return rec(arr);

                  }

                  function succesHandler(data, index) {

                  // Here i can alter 'data'
                  data['finishedPromiseNr'] = index;

                  console.log("promise test ", data, index);

                  console.log("Go for next ");

                  return data;

                  }

                  function errorHandler(err) {
                  console.log("Error occurred ", err);
                  }

                  function submitAjaxData(form, datafield) {
                  console.log("called submitAjaxData ", datafield);
                  //var loadurl = domainName + "/ajax-call-handler";

                  // Mock some requests with delayed responses
                  // https://reqres.in/#console
                  var loadurl = "https://reqres.in/api/users?delay=" + datafield.fakeDelay;
                  return $.ajax({
                  url: loadurl,
                  method: "GET",
                  data: datafield
                  });
                  }

                  function formPostSubmission(form) {
                  var parts = ['a', 'b', 'c'];
                  var i = 0;
                  let poll = ;
                  parts.forEach(function(entry) {
                  i++;

                  // 'datafield' was not assigned with var or let
                  // Reassigning it on each loop will allow 'datafield' to pass in the anonymous function below
                  let datafield = {
                  answer: entry,
                  displayOrder: i,
                  ajaxName: 'statementPartialSubmit',
                  fakeDelay: parts.length - i
                  };

                  // Wrong: submitAjaxData is called, that means, the requests are sent immediately.
                  // poll.push( $.when(submitAjaxData(form, datafield) );

                  // Correct: Wrap and return $.when into a function otherwise 'submitAjaxData' will trigger the requests
                  poll.push(() => $.when(submitAjaxData(form, datafield)));

                  });

                  PromiseAllSeq(poll, succesHandler).then(responseList => {

                  console.log('final response');
                  console.log(responseList);

                  }).catch(errorHandler)


                  }

                  formPostSubmission(null);

                  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>








                  console.clear();
                  /**
                  * Promises will wait for each other and will return any.
                  * If a promise is rejected it will stop.
                  * @param arr - (Promise<any> | ()=>Promise<any>) - Accepts promise or a function that returns a promise
                  * @param callback(response, index) - If callback 'returns' it will overwrite the current response. Useful for changing the response.
                  * @returns any
                  */
                  const PromiseAllSeq = (arr, callback) => {

                  let result = ;

                  if (typeof callback !== 'function') {
                  callback = () => {};
                  }

                  const rec = (arr) => {

                  return new Promise((resolve, reject) => {

                  if (arr.length) {

                  (typeof arr[0] === 'function' ? arr[0]() : arr[0]).then(res => {

                  let cb = callback(res, result.length);

                  result = result.concat(typeof cb !== 'undefined' ? cb : res);

                  arr.splice(0, 1);

                  resolve(arr.length ? rec(arr) : result);

                  }).catch(err => {

                  reject(err);

                  })

                  } else {

                  resolve(result);

                  }

                  })

                  }

                  return rec(arr);

                  }

                  function succesHandler(data, index) {

                  // Here i can alter 'data'
                  data['finishedPromiseNr'] = index;

                  console.log("promise test ", data, index);

                  console.log("Go for next ");

                  return data;

                  }

                  function errorHandler(err) {
                  console.log("Error occurred ", err);
                  }

                  function submitAjaxData(form, datafield) {
                  console.log("called submitAjaxData ", datafield);
                  //var loadurl = domainName + "/ajax-call-handler";

                  // Mock some requests with delayed responses
                  // https://reqres.in/#console
                  var loadurl = "https://reqres.in/api/users?delay=" + datafield.fakeDelay;
                  return $.ajax({
                  url: loadurl,
                  method: "GET",
                  data: datafield
                  });
                  }

                  function formPostSubmission(form) {
                  var parts = ['a', 'b', 'c'];
                  var i = 0;
                  let poll = ;
                  parts.forEach(function(entry) {
                  i++;

                  // 'datafield' was not assigned with var or let
                  // Reassigning it on each loop will allow 'datafield' to pass in the anonymous function below
                  let datafield = {
                  answer: entry,
                  displayOrder: i,
                  ajaxName: 'statementPartialSubmit',
                  fakeDelay: parts.length - i
                  };

                  // Wrong: submitAjaxData is called, that means, the requests are sent immediately.
                  // poll.push( $.when(submitAjaxData(form, datafield) );

                  // Correct: Wrap and return $.when into a function otherwise 'submitAjaxData' will trigger the requests
                  poll.push(() => $.when(submitAjaxData(form, datafield)));

                  });

                  PromiseAllSeq(poll, succesHandler).then(responseList => {

                  console.log('final response');
                  console.log(responseList);

                  }).catch(errorHandler)


                  }

                  formPostSubmission(null);

                  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>





                  console.clear();
                  /**
                  * Promises will wait for each other and will return any.
                  * If a promise is rejected it will stop.
                  * @param arr - (Promise<any> | ()=>Promise<any>) - Accepts promise or a function that returns a promise
                  * @param callback(response, index) - If callback 'returns' it will overwrite the current response. Useful for changing the response.
                  * @returns any
                  */
                  const PromiseAllSeq = (arr, callback) => {

                  let result = ;

                  if (typeof callback !== 'function') {
                  callback = () => {};
                  }

                  const rec = (arr) => {

                  return new Promise((resolve, reject) => {

                  if (arr.length) {

                  (typeof arr[0] === 'function' ? arr[0]() : arr[0]).then(res => {

                  let cb = callback(res, result.length);

                  result = result.concat(typeof cb !== 'undefined' ? cb : res);

                  arr.splice(0, 1);

                  resolve(arr.length ? rec(arr) : result);

                  }).catch(err => {

                  reject(err);

                  })

                  } else {

                  resolve(result);

                  }

                  })

                  }

                  return rec(arr);

                  }

                  function succesHandler(data, index) {

                  // Here i can alter 'data'
                  data['finishedPromiseNr'] = index;

                  console.log("promise test ", data, index);

                  console.log("Go for next ");

                  return data;

                  }

                  function errorHandler(err) {
                  console.log("Error occurred ", err);
                  }

                  function submitAjaxData(form, datafield) {
                  console.log("called submitAjaxData ", datafield);
                  //var loadurl = domainName + "/ajax-call-handler";

                  // Mock some requests with delayed responses
                  // https://reqres.in/#console
                  var loadurl = "https://reqres.in/api/users?delay=" + datafield.fakeDelay;
                  return $.ajax({
                  url: loadurl,
                  method: "GET",
                  data: datafield
                  });
                  }

                  function formPostSubmission(form) {
                  var parts = ['a', 'b', 'c'];
                  var i = 0;
                  let poll = ;
                  parts.forEach(function(entry) {
                  i++;

                  // 'datafield' was not assigned with var or let
                  // Reassigning it on each loop will allow 'datafield' to pass in the anonymous function below
                  let datafield = {
                  answer: entry,
                  displayOrder: i,
                  ajaxName: 'statementPartialSubmit',
                  fakeDelay: parts.length - i
                  };

                  // Wrong: submitAjaxData is called, that means, the requests are sent immediately.
                  // poll.push( $.when(submitAjaxData(form, datafield) );

                  // Correct: Wrap and return $.when into a function otherwise 'submitAjaxData' will trigger the requests
                  poll.push(() => $.when(submitAjaxData(form, datafield)));

                  });

                  PromiseAllSeq(poll, succesHandler).then(responseList => {

                  console.log('final response');
                  console.log(responseList);

                  }).catch(errorHandler)


                  }

                  formPostSubmission(null);

                  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 13 '18 at 23:51









                  darklightcodedarklightcode

                  1,25689




                  1,25689























                      -1














                      async: false 


                      is the best option in your case






                      share|improve this answer

















                      • 1




                        While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
                        – Clijsters
                        Nov 13 '18 at 12:29










                      • async: false was deprecated years ago because of negative user experience.
                        – Tyler Roper
                        Nov 13 '18 at 23:58


















                      -1














                      async: false 


                      is the best option in your case






                      share|improve this answer

















                      • 1




                        While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
                        – Clijsters
                        Nov 13 '18 at 12:29










                      • async: false was deprecated years ago because of negative user experience.
                        – Tyler Roper
                        Nov 13 '18 at 23:58
















                      -1












                      -1








                      -1






                      async: false 


                      is the best option in your case






                      share|improve this answer












                      async: false 


                      is the best option in your case







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Nov 13 '18 at 9:12









                      Joby JosephJoby Joseph

                      11




                      11








                      • 1




                        While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
                        – Clijsters
                        Nov 13 '18 at 12:29










                      • async: false was deprecated years ago because of negative user experience.
                        – Tyler Roper
                        Nov 13 '18 at 23:58
















                      • 1




                        While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
                        – Clijsters
                        Nov 13 '18 at 12:29










                      • async: false was deprecated years ago because of negative user experience.
                        – Tyler Roper
                        Nov 13 '18 at 23:58










                      1




                      1




                      While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
                      – Clijsters
                      Nov 13 '18 at 12:29




                      While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
                      – Clijsters
                      Nov 13 '18 at 12:29












                      async: false was deprecated years ago because of negative user experience.
                      – Tyler Roper
                      Nov 13 '18 at 23:58






                      async: false was deprecated years ago because of negative user experience.
                      – Tyler Roper
                      Nov 13 '18 at 23:58




















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53275216%2fhow-to-make-a-foreach-loop-wait-for-each-ajax-function-to-finish%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      Hercules Kyvelos

                      Tangent Lines Diagram Along Smooth Curve

                      Yusuf al-Mu'taman ibn Hud