Return value from last AJAX request in AJAX chain that is inside a for loop
I have a for
loop, and in one iteration (of something) I need to make four AJAX requests, then wait until result from the last request.
Now I've got only how to pass data from previous promise to another, like in this cool answer, but I need to return the value from the last AJAX call to the outer array (and wait until the last AJAX call is done) and then continue other functions out of the loop.
attaches.forEach(function(attach)) {
if(attach.val == "val1"){
attachments.push(attach.val1);
}
if(attach.val == "val2"){
attachments.push(attach.val2);
}
if(attach.val == val3){
function func1(){
var params = [param1,param2];
return $.post(api, params.join('&'))
}
function func2(){
console.log('1111');
return new Promise(function(resolve, reject)) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
}
xhr.open('GET', img_src);
xhr.responseType = 'blob';
xhr.send();
});
}
function uploadPhoto(upload_url, bulbSend){
console.log('<Del><F7> function uploadPhoto');
return $.ajax({
url: upload_url,
type: 'POST',
data: bulbSend,
dataType: 'json',
processData: false,
contentType: false,
});
}
function saveResult(params){
return $.post(api, params.join('&'))
}
func1().then(fun1hand()).then(console.log('a32w436bya3b7naua'));
function fun1hand(){
return function(dat4a) {
return func2().then(func2hand(dat4a));
};
}
function func2hand(dat4a){
console.log('2222');
return function(datums){
console.log('3333');
var upload_url = dat4a.upload_url;
console.log('UPLOAD__URL BEFORE PROMISE '+upload_url);
var bulbSend = new FormData();
bulbSend.append('file1', datums, 'file.jpg');
return uploadPhoto(upload_url,bulbSend).then(func3hand());
}
}
function func3hand(){
return function(data2){
var params = [data2.param1, data2.param2, data2.param3];
return saveResult(params).then(pushToAttachmentsHandler());
}
}
function pushToAttachmentsHandler(){
return function(data3){
console.log('PUSUSUSUSSUSUSUUSUS PUSHHHHHHH PUSH DA BAUTTON');
console.log(attachments);
return pushDat(data3).then(console.log(attachments));
}
}
function pushDat(data3){
console.log('1111');
return new Promise(function(resolve, reject) {
attachments.push(data3.param3+"_"+data3.param1));
console.log('11111111111');
});
}
}
});
Callbacks or promises are capable of handling that kind of async control flow...
Assuming your original non working code is...
for(var i=0; i < 10; i++){
$.get('http://example.com/rest/users/'+i);
$.get('http://example.com/rest/posts/'+i);
$.get('http://example.com/rest/comments/'+i);
$.get('http://example.com/rest/events/'+i);
}
Callbacks...
var i = 1;
getSet(repeater);
// define a repeater function to be used as recursive callback
function repeater (){
// increment counter
i++;
// if we still have items to process, get another set
if(i < 10){
getSet(repeater);
}
}
function getSet(cb){
// define queue
var counter = 0;
// make four api calls, defining success callbacks, which call the
// originally passed callback if the counter reaches 0. Increment counter before each request. This means the callback fires only for the last result
counter++;
$.get('http://example.com/rest/users/'+i, handleSuccess);
counter++;
$.get('http://example.com/rest/posts/'+i, handleSuccess);
counter++;
$.get('http://example.com/rest/comments/'+i, handleSuccess);
counter++;
$.get('http://example.com/rest/events/'+i, handleSuccess);
function handleSuccess(data){
// do something with data
--counter || cb();
}
}
This pattern works something like this...
getSet
is called the first time, with a repeater
function that is expected to be called once all async requests are done. The getSet
function increments a stack when making async calls, and decrements in the async callbacks, calling the repeater
when the stack settles back to zero and there are no more async jobs in the queue. The repeater
callback then repeats the whole process, calling getSet
and passing itself as the callback until a condition is met.
It looks simple, for both async and sync ajax requests you may use:
var myVar;
yourLoop(function() {
yourAjax(function(result) {
myVar = result;
});
});
Change your variable value on ajax success(finish) callback
UPD:
If you need a callback on the last result I may suggest you this hackly option:
var myVar, timeout;
yourLoop(function() {
yourAjax(function(result) {
myVar = result;
clearTimeout(timeout);
timeout = setTimeout(function() {
// do something . . .
console.log('last result', myVar);
}, 1000);
});
});
Note: change 1000
to expected maximum response time
上一篇: 在for循环中调用一个xhr内的ajax