我正在编写一些依赖于一些异步方法调用的javascript,
var one = asyncCall();
var two = differentAsyncCall();
我知道我可以处理任何一个返回值,如此
var one = asyncCall(function(results){
//do stuff
});
var two = differentAsyncCall(function(results){
//do more
});
我想用它们执行操作,所以要做到这一点,必须完成两个异步调用。我知道我可以做类似的事情:
asyncCall(function(results){
var firstReturn = results;
differentAsyncCall(function(results2){
var secondReturn = results2;
//do stuff now that they're both defined.
});
});
我很好奇是否可以使用setInterval或setTimeout来执行以下操作:
var one = asyncCall(function(results){
return results;
});
var two = differentAsyncCall(function(results){
return results;
});
window.setInterval(function(){
if( one && two){
//do stuff now that they're defined
//remove the timer
}
},250);
答案 0 :(得分:3)
这是一个名为Promises的概念,可以在这里使用。 Promise是延迟对象概念的一部分。
这个想法是将异步调用分配给两个变量。当两个变量都可用时,请采取一些操作,这就是您要做的事情。
我使用过jQuery版本,其文档可以在这里找到。 http://api.jquery.com/jquery.when/
很容易理解。我不知道如何在纯Javascript中实现它。你最好使用任何异步库
答案 1 :(得分:1)
这是使用Promises / Deferreds的一个很好的用例,但这是另一个概念,需要包含一个库(至少目前为止)。
当你使用纯javascript(没有库)时,可以在某处添加这个简单的帮助方法:
function whenAll(promises, doneProperty, callback){
promises[doneProperty] = true;
for(var key in promises)
if(promises[key] == false) return false;
if(callback) callback();
return true;
}
(以下示例包含3个需要完成的异步调用)
然后你会这样做:
//This object contains all the async calls needed to be completed, key is the name
var promises = {"asyncCall1": false, "asyncCall2": false, "asyncCall3": false};
//And the magic comes here:
var results1, results2, results3; //These will contain the results
(function(whenAllCallback){
asyncCall1(function(results){
results1 = results;
whenAll(promises, "asyncCall1", whenAllCallback);
});
asyncCall2(function(results){
results2 = results;
whenAll(promises, "asyncCall2", whenAllCallback);
});
asyncCall3(function(results){
results3 = results;
whenAll(promises, "asyncCall3", whenAllCallback);
});
})(function(){
//This executes when all calls have been completed
alert(results1);
alert(results2);
alert(results3);
});
请注意,3个异步调用可以按任何顺序结束,并且在完成所有操作后,将根据需要执行回调。
这种语法在开始时可能很难,但是一旦你习惯它,它就变得容易了。在进入真正的承诺之前,您可以使用此代码。
来自玻利维亚拉巴斯的欢呼声答案 2 :(得分:0)
我之前的答案的另一个版本,它接受返回值作为最终回调中的参数,并使用promises数组而不是object(更简单):
function whenAll(promisesKeys, doneProperty, callback, returnValue){
var returnValues = promisesKeys.returnValues = promisesKeys.returnValues || new Array(promisesKeys.length);
returnValues[promisesKeys.indexOf(doneProperty)] = (returnValue === undefined ? null : returnValue);
for(var i=0; i < returnValues.length; i++)
if(returnValues[i] === undefined) return false;
delete promisesKeys.returnValues;
callback.apply(this, returnValues);
return true;
}
这是一个示例用法:
//This array contains all the async calls keys needed to be completed
var promisesKeys = ["call1", "call2", "call3"];
//And the magic comes here:
(function(whenAllCallback){
//Intentionally call the methods in different order
asyncCall2(function(results){
whenAll(promisesKeys, "call2", whenAllCallback, results);
});
asyncCall1(function(results){
whenAll(promisesKeys, "call1", whenAllCallback, results);
});
asyncCall3(function(results){
whenAll(promisesKeys, "call3", whenAllCallback, results);
});
})(function(results1, results2, results3){ //These come in the same order as in the initial array
//This executes when all calls have been completed
console.log("ALL FINISHED:!");
console.log(results1);
console.log(results2);
console.log(results3);
});
jsfiddle:http://jsfiddle.net/edgarinvillegas/B3x72/
干杯