2012-11-12 132 views
3

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

例如,我有这样的方法:

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/

什么是最佳解决方案?

干杯。

回答

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

你开始运行execute0功能,并且当它这样做,你从头再来(通过递归),但这次1。在递归之前,您必须检查是否继续:只有在增加的值仍低于r时才这样做。

+0

很好。我做了一个小改动来处理数组:http://jsfiddle.net/vtortola/ZaCp8/谢谢。 – vtortola

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)() 
+0

这是一个很好的解决方案。该死的,我将不得不再次得到我的JavaScript书籍:D。非常感谢。 – vtortola