来自 for 循环内的 AJAX 链中最后一个 AJAX 请求的返回值
Posted
技术标签:
【中文标题】来自 for 循环内的 AJAX 链中最后一个 AJAX 请求的返回值【英文标题】:Return value from last AJAX request in AJAX chain that is inside a for loop 【发布时间】:2016-07-06 15:32:00 【问题描述】:我有一个for
循环,并且在一次迭代中(某事)我需要发出四个 AJAX 请求,然后等到最后一个请求的结果。
现在我只知道如何将数据从先前的承诺传递给另一个承诺,例如in this cool answer,但我需要将最后一次 AJAX 调用的值返回到外部数组(并等到最后一次 AJAX 调用完成) 然后在循环外继续其他函数。
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');
);
);
循环外的函数在 console.log('3333')
内的 Promise 之前开始其 console.log
s...但它们需要等待直到循环内的 AJAX 调用完成并且循环完成。
现在我需要在超时后重复 AJAX,如果它被拒绝(每秒服务器请求限制) - 我如何在我的代码中为原生 XMLHttpRequest()
设置它,这是在 promise 中,对于 jQuery AJAX 调用是退了吗?
【问题讨论】:
@Roland Starke 我的代码很脏,只是以某种方式编辑 【参考方案1】:看起来很简单,对于异步和同步 ajax 请求,您都可以使用:
var myVar;
yourLoop(function()
yourAjax(function(result)
myVar = result;
);
);
在 ajax 成功(完成)回调中更改变量值
UPD:
如果您需要对最后一个结果进行回调,我可能会建议您使用这个 hackly 选项:
var myVar, timeout;
yourLoop(function()
yourAjax(function(result)
myVar = result;
clearTimeout(timeout);
timeout = setTimeout(function()
// do something . . .
console.log('last result', myVar);
, 1000);
);
);
注意:将 1000
更改为预期的最大响应时间
【讨论】:
【参考方案2】:回调或承诺能够处理这种异步控制流...
假设你原来的非工作代码是……
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);
回调...
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();
这种模式的工作原理是这样的......
getSet
第一次被调用,repeater
函数预计会在所有异步请求完成后被调用。 getSet
函数在进行异步调用时递增堆栈,并在异步回调中递减,当堆栈恢复为零并且队列中没有更多异步作业时调用repeater
。然后repeater
回调重复整个过程,调用getSet
并将自身作为回调传递,直到满足条件。
【讨论】:
为什么不 cb();在第一个异步回调中运行?最后一个ajax调用中'or'运算符的含义首先与它不同吗?我需要等待来自 prev ajax 的数据来调用下一个...我需要 ajax 链只有当循环中出现某些东西时,如果迭代有东西,不需要 ajax > 它只是将数据推送到外部数组中...我认为我不明白你的好答案的概念 好的,所以如果您遇到的问题是代码有时是异步的,有时是同步的 - 那么只需将其编码为一直是异步的,当您需要simply push
时只需触发立即使用数据回调,而不是在 ajax 回调中。这有帮助吗?
我需要以前的 ajax 请求中的值来跟随类似这样的 ajax ( $.get('example.com/+i', function(data1) --counter || cb(); ); $ .get('example.com/+data1.something', function(data2) ... 对数据 1 和数据 2 做一些事情 .... --counter || cb(); ); 并分享到最后 ... i需要在下一个之前等待来自第一个的请求。但现在我不明白 --counter || cb(); 语句......在你的例子中请求应该等到上一个?为什么 var i = 1;
我在link, link,link 找到了一些相关信息,但为什么是 cb();当计数器第一次递减时不执行?因为第一次计数器== 0 ...?您的代码会在下一个之前提供来自第一个 ajax 的等待请求吗?对不起我的愚蠢问题
ajax 成功回调比周围的代码发生得晚得多。它们只有在成功满足 ajax 请求后才会执行。在任何成功回调减少它之前,计数器会增加四次。我更新了答案,希望能让你更清楚以上是关于来自 for 循环内的 AJAX 链中最后一个 AJAX 请求的返回值的主要内容,如果未能解决你的问题,请参考以下文章