在执行下一步之前需要进行多个异步调用JS
问题描述:
我有一个数组,它可以容纳未知数量的索引。每个索引用于通过ajax
呼叫发送数据。我正在通过for loop
收集成功调用的数据并将其推入空数组。在未知数量的调用结束时,我需要在我的视图中使用新聚集的数组。 newDataArray
在循环完成之前在底部执行,因此它仍然是空的。我如何完成所有的电话,然后做底部的事情?在执行下一步之前需要进行多个异步调用JS
如果有帮助,我正在使用Flux模式进行React。但是同样的问题可能不会在React中完成。这里是什么,我试图做一个模拟样本:
JS
case 'execute-calls':
//This is the new array to push to
var newDataArray = [];
//Url to call
var url = 'http://dev.markitondemand.com/Api/v2/Quote/jsonp';
for(let i = 0; i < payload.data.length; i++){
//given array of data that needs to be sent with call
let symb = { symbol: payload.data[i]};
$.ajax({
data: symb,
url: url,
dataType: "jsonp",
})
.done(function(data){
let updatedData = {
//...data that is stored from response
};
newDataArray.push(updatedData);
})
.fail(function(error){
//console.log(error);
});
}
//This will be updating the state object which is above the switch cases
//However this is ran before the end of the loops so newDataArray is empty
var updateTicker = {
updatedTicker: true,
updatedTickerSymbols: newDataArray
};
assign(stockData,updateTicker);
getStockData.emitChange();
break;
答
可以使使用$.ajax()实际返回deferred object ,并用它来创建一个延迟数组。例如
var symbols = [1, 2, 3, 4];
var deferreds = symbols.map(function (symbol) {
return $.ajax({
url: 'http://dev.markitondemand.com/MODApis/Api/v2/Quote/jsonp',
data: { symbol: symbol },
dataType: 'jsonp'
});
});
您可以用$.when()一次解决多个延期。但是有一个复杂的问题,$ .when()需要一个参数列表而不是数组。我们可以通过使用Function#apply
来解决这个问题。
要添加到并发症,回调函数也被称为参数列表。由于我们不知道有多少个参数,我们将使用arguments
伪数组。由于参数不是实际的数组,我们将通过使用Function#call
对Array#prototype
进行循环。
$.when(...deferreds).done((...responses) => {
responses.forEach((response) => {
console.log(response[0].Message);
});
});
答
当过你正在处理Ajax调用,并有在所有异步年底做一些操作调用,那么更好的选择会是使用Callback
函数。
修改代码以使用回调,
function AsyncLoopHandler(index) {
if (index > payload.data.length) {
// all the indexes have finished ajax calls do your next step here
var updateTicker = {
updatedTicker: true,
updatedTickerSymbols: newDataArray
};
assign(stockData, updateTicker);
getStockData.emitChange();
}
else {
//given array of data that needs to be sent with call
let symb = { symbol: payload.data[index] };
$.ajax({
data: symb,
url: url,
dataType: "jsonp",
})
.done(function (data) {
let updatedData = {
//...data that is stored from response
};
newDataArray.push(updatedData);
AsyncLoopHandler(index++); // call the function again with new index
})
.fail(function (error) {
//console.log(error);
});
}
}
现在启动这个递归函数只是路过
AsyncLoopHandler(0);
因此,所有的Ajax调用将被执行的索引0
启动如同一个同步请求一样,并且if
检查将会看看所有的索引是否完整,然后运行你的逻辑。让我知道,如果这有助于
答
建议使用承诺,逻辑想在新标准
var urls= [x,x,x,x];
var results = [];
var qs = $.map(urls,function(url){
return function(){
var deferred = Q.defer();
$.ajax({
success:function(){
results.push(url)
deferred.reslove();
},error:function(){
deferred.reslove();
}
})
return deferred;
}
})
Q.all(qs).then(function(){
console.log(results)
});
或使用产量和合作https://github.com/kriskowal/q
这种方式似乎最直观:
如果您使用ES6这是更优雅[修订包括失败()调用]
。感谢你的回答。你如何看到从响应中是否发生错误?它会被存储在其中一个索引中吗? '$ .when.apply($,deferreds).done(function(response){'那里的控制台日志记录响应会显示错误? – Chipe
好点,还有一个失败的回调函数,当遇到第一个错误时会调用它我相应地更新了代码。 –