jQuery延迟了一系列函数

Val*_*Zho 11 javascript jquery asynchronous sequential jquery-deferred

我有一个充满这样功能的对象:

var functions = {
    fun1 : function(){ ... }
    fun2 : function(){ ... }
    fun3 : function(){ ... }
};
Run Code Online (Sandbox Code Playgroud)

对象键都在数组中引用,如下所示:

var funList = ['fun1','fun2','fun3'];
Run Code Online (Sandbox Code Playgroud)

我一直在使用该数组来运行所有函数:

$.each(funList, function(i,v){
    functions[v].call(this, args);
});
Run Code Online (Sandbox Code Playgroud)

我的问题是这个,我需要一些方法来推迟所有功能的运行,这样:

  1. 在$ .each循环中,函数以串行方式运行
  2. 一种延迟后续代码运行的方法,直到数组/对象中的所有函数都完成为止.

我已经读过我应该使用$ .map方法,但是我很难把它包裹起来.

Val*_*Zho 8

哇...这是一个练习 - $.延期()有点难以让我的思绪缠身,但我把它全部都搞定了我想要的!我不知道这是多么简化 - 也许其他人可以使它更有效率.

它的要点是使用.pipe()创建一个延迟链.

编辑:我的代码(下面)在参考密钥列表中不包含少于2个对象.我更新了jsfiddle以使用任何大小的键列表.


您可以在JSFiddle上看到以下所有工作:http://jsfiddle.net/hBAsp/3/


以下是我如何解决它的一步一步:

  1. 从一个充满函数的对象和一组引用键开始(按照您希望它们处理的顺序).函数应该期望在完成时接收要解析的延迟对象:

    var obj = {
        one: function(dfd){
            /* do stuff */
            dfd.resolve();
        },
        two: function(dfd){...},
        three: function(dfd){...},
        etc...
    };
    var keys=['one','two','three', etc...];`
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建主延迟包装器将promise传递给初始化函数.我们将把代码添加到函数中:

    var mainDeferred = $.Deferred(function(mainDFD){
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在初始化函数内部,创建一个延迟数组,手动创建第一个延迟对象:

    var dfds = [$.Deferred()];
    
    Run Code Online (Sandbox Code Playgroud)
  4. 接下来,使用for循环遍历第二个到我们的键列表中的倒数第二个项目.我们将成为:

    1. 为我们单步执行的每个项目创建一个延迟对象
    2. 设置一个匿名函数,它将从我们的obj运行与键相关的函数,传递给它来解析我们新创建的Deferred对象
    3. 将新创建的函数传递给先前创建的Deferred对象(这就是为什么我们必须手动创建第一个)
    4. 您必须在for列表中使用一个封闭的循环来解决JavaScript范围问题

      for (i=1; i<keys.length-1; i++){
          (function(n){
              dfds.push($.Deferred());
              dfds[i-1].pipe(function(){
                  obj[keys[n]].call(this,dfds[n]);
              });
          })(n);
      };
      
      Run Code Online (Sandbox Code Playgroud)
  5. 手动创建最后一个匿名函数并将其传递到列表中倒数第二个延迟对象.我们手动执行此操作是因为我们想要传递给它的主要延迟对象以便解析,以便整个shebang在最后一个进程运行后立即激活:

    dfds[keys.length-2].pipe(function(){
        obj[keys[keys.length-1]].call(this,mainDFD);
    });
    
    Run Code Online (Sandbox Code Playgroud)
  6. 现在我们构建了整个管道,我们所要做的就是触发第一个对象并为其分配第一个延迟解决方案:

    obj[keys[0]].call(this,dfds[0]);
    
    Run Code Online (Sandbox Code Playgroud)
  7. 只需要关闭我们的主延迟初始化函数(这将在创建延迟时立即触发:

    });
    
    Run Code Online (Sandbox Code Playgroud)
  8. 现在我们还可以将一个函数传递给主对象,以便在我们之前的所有元素都运行之后运行:

    mainDeferred.pipe(function(){
        /* do other stuff */    
    });
    
    Run Code Online (Sandbox Code Playgroud)