How to make a forEach loop wait for each Ajax function to finish
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
add a comment |
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
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
add a comment |
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
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
javascript jquery ajax loops
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
add a comment |
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
add a comment |
4 Answers
4
active
oldest
votes
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)
})
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
|
show 2 more comments
you could use this solution by using await
, for example :
for (let f of files) {
await $.ajax({/* your ajax config*/ });
}
add a comment |
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>
add a comment |
async: false
is the best option in your case
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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)
})
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
|
show 2 more comments
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)
})
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
|
show 2 more comments
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)
})
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)
})
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
|
show 2 more comments
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
|
show 2 more comments
you could use this solution by using await
, for example :
for (let f of files) {
await $.ajax({/* your ajax config*/ });
}
add a comment |
you could use this solution by using await
, for example :
for (let f of files) {
await $.ajax({/* your ajax config*/ });
}
add a comment |
you could use this solution by using await
, for example :
for (let f of files) {
await $.ajax({/* your ajax config*/ });
}
you could use this solution by using await
, for example :
for (let f of files) {
await $.ajax({/* your ajax config*/ });
}
answered Nov 13 '18 at 21:27
Sari MasriSari Masri
1297
1297
add a comment |
add a comment |
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>
add a comment |
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>
add a comment |
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>
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>
answered Nov 13 '18 at 23:51
darklightcodedarklightcode
1,25689
1,25689
add a comment |
add a comment |
async: false
is the best option in your case
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
add a comment |
async: false
is the best option in your case
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
add a comment |
async: false
is the best option in your case
async: false
is the best option in your case
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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