3

我试图链接承诺,而不是管道,只是链接。

例如,我有这个方法:

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;
};

我想多次执行这个方法,但是一个接一个。我创建了一个比 using 更有效的方法eval,但我对 using 不太满意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/

最好的解决方案是什么?

干杯。

4

2 回答 2

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.

于 2012-11-12T18:24:16.523 回答
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)()
于 2012-11-12T18:36:46.063 回答