我试图将承诺链接起来,而不是管道,只是链接。
例如,我有这个方法:
var execute = function(x){
// this could be an AJAX call
var d= $.Deferred();
console.log('Begin ' + x);
setTimeout(function(){
console.log('End ' + x);
d.resolve();
},500);
return d;
};
我想多次执行此方法,但是一个接一个地执行。我创建了一个方法,而不是使用eval
,但我对使用eval
感到不满意:
var executeTimes = function(r){
var s = '';
for(var i=0;i<r;i++){
s = s + 'execute('+i+')';
if(i!==r-1)
s = s + '.then(function(){';
}
for(var i=0;i<r-1;i++){
s= s+'})';
}
eval(s);
}
我的想法是,executeTimes(3);
你得到这个输出:
Begin 0
End 0
Begin 1
End 1
Begin 2
End 2
我在这里创建了一个实例:http://jsfiddle.net/vtortola/Cfe5s/
什么是最好的解决方案?
干杯。
答案 0 :(得分:4)
递归看起来很整洁:http://jsfiddle.net/Cfe5s/3/。
var executeTimes = function(r) {
(function recurse(i) {
execute(i).then(function() {
if(i + 1 < r) {
recurse(i + 1);
}
});
})(0);
};
你启动一个用execute
运行0
的函数,当它完成时你重新开始(通过递归),但这次是1
。在递归之前,您必须检查是否继续:只有当递增的值仍然低于r
时才这样做。
答案 1 :(得分:2)
我的方法类似于你的方法,但我没有连接字符串,而是嵌套函数调用:P
var executeTimes = function(r){
// The last (inner-most) step does nothing.
// just in the case we pass r <= 0
var f = function(){};
for(; r > 0 ; --r){
// Create closure with call to execute( ... ).then( ... )
f = (function(_f, _r){
return function(){ execute(_r).then(_f); };
})(f, r - 1);
}
return f;
}
它返回一个行为符合你想要的函数。如果你这样做:
executeTimes(3)()
这会产生与您的示例相同的输出。
可以轻松地调整此示例以支持任何函数和任何最后一步(我假设函数toExec
想要接收调用的“数字”):
var executeTimes2 = function(toExec /*a function*/,
steps /*a number*/,
finalStep /*a function*/)
{
// The last (inner-most) step.
// just in the case we pass r <= 0
var f = finalStep? finalStep : function(){};
for(; steps > 0 ; --steps){
// Create closure with call to execute( ... ).then( ... )
f = (function(_f, _r){
return function(){ toExec(_r).then(_f); };
})(f, steps - 1);
}
return f;
}
所以你的函数可以这样调用3次:
executeTimes2(execute, 3)()