【问题标题】:Chain jQuery promises链式 jQuery 承诺
【发布时间】:2012-11-13 02:49:41
【问题描述】:

我正在尝试链接承诺,而不是管道,只是链接。

比如我有这个方法:

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/

最好的解决方案是什么?

干杯。

【问题讨论】:

    标签: jquery asynchronous eval promise


    【解决方案1】:

    这里的递归看起来很简洁:http://jsfiddle.net/Cfe5s/3/

    var executeTimes = function(r) {
      (function recurse(i) {
        execute(i).then(function() {
          if(i + 1 < r) {
            recurse(i + 1);
          }
        });
      })(0);
    };
    

    您使用0 启动一个运行execute 的函数,完成后您重新开始(通过递归),但这次使用1。在递归之前,你必须检查是否继续:只有当增量值仍然低于r时才这样做。

    【讨论】:

    【解决方案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)()
    

    【讨论】:

    • 这是一个很好的解决方案。该死的,我将不得不再次获得我的 javascript 书籍:D。非常感谢。
    猜你喜欢
    • 2021-02-27
    • 2012-07-17
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 2014-08-12
    • 2016-12-08
    • 1970-01-01
    相关资源
    最近更新 更多