在执行下一步 JS 之前需要进行多次异步调用
Need to make multiple Async calls before executing next step JS
我有一个数组,其中可以包含未知数量的索引。每个索引都用于通过 ajax
调用发送数据。我正在循环使用 for loop
从成功调用中收集数据并将其推入一个空数组。在未知数量的调用结束时,我需要在我的视图中使用新收集的数组。 newDataArray
在循环完成之前在底部执行,因此它仍然是空的。如何完成所有调用然后执行底部的操作?
如果有帮助,我正在使用 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 调用并且必须在所有异步调用结束时执行一些操作时,更好的选择是使用 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);
});
}
}
现在启动这个递归函数只需通过传递索引 0 来启动它。
AsyncLoopHandler(0);
所以所有的ajax调用将一个接一个地执行,就好像它是一个同步请求一样,并且if
检查将查看所有索引是否完整然后[=24= 】 你的逻辑。让我知道这是否有帮助
建议使用promise,逻辑如上
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 )
});
或在新标准中使用 yield 和 co
您可以利用 $.ajax() actually returns a 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
伪数组。由于 arguments 不是 actual 数组,我们将通过在 Array#prototype
.
上使用 Function#call
来遍历它
$.when.apply($, deferreds).done(function () {
Array.prototype.forEach.call(arguments, function (response) {
console.log(response[0].Message);
});
}).fail(function (jqXHR, textStatus, error) {
console.error(error);
});
[已更新 以包含 fail() 调用]
如果你使用的是 ES6,这会更优雅:
$.when(...deferreds).done((...responses) => {
responses.forEach((response) => {
console.log(response[0].Message);
});
});
我有一个数组,其中可以包含未知数量的索引。每个索引都用于通过 ajax
调用发送数据。我正在循环使用 for loop
从成功调用中收集数据并将其推入一个空数组。在未知数量的调用结束时,我需要在我的视图中使用新收集的数组。 newDataArray
在循环完成之前在底部执行,因此它仍然是空的。如何完成所有调用然后执行底部的操作?
如果有帮助,我正在使用 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 调用并且必须在所有异步调用结束时执行一些操作时,更好的选择是使用 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);
});
}
}
现在启动这个递归函数只需通过传递索引 0 来启动它。
AsyncLoopHandler(0);
所以所有的ajax调用将一个接一个地执行,就好像它是一个同步请求一样,并且if
检查将查看所有索引是否完整然后[=24= 】 你的逻辑。让我知道这是否有帮助
建议使用promise,逻辑如上
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 )
});
或在新标准中使用 yield 和 co
您可以利用 $.ajax() actually returns a 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
伪数组。由于 arguments 不是 actual 数组,我们将通过在 Array#prototype
.
Function#call
来遍历它
$.when.apply($, deferreds).done(function () {
Array.prototype.forEach.call(arguments, function (response) {
console.log(response[0].Message);
});
}).fail(function (jqXHR, textStatus, error) {
console.error(error);
});
[已更新 以包含 fail() 调用]
如果你使用的是 ES6,这会更优雅:
$.when(...deferreds).done((...responses) => {
responses.forEach((response) => {
console.log(response[0].Message);
});
});