有没有人知道JS Chaining库允许延迟执行方法?

时间:2013-06-05 20:23:18

标签: javascript

我正在寻找一个允许我轻松地将方法链接在一起的库,但推迟执行,直到在链中进一步提供参数:

chain
    .scanDirectory  ( '/path/to/scan' )
        .recursively()
        .for        ( /\.js$/i        )
    .cache()
    .provideTo      ( '0.locals'      )
        .as         ( 'scripts'       )
    .defer();

重要的是scanDirectory函数后面的代码实际上并没有被调用,直到它被定义为应该递归并查找.js文件。

我不太确定如何对其进行逻辑设置,以便我可以执行以下操作:

chain
    .scanDirectory( '/path/to/scan' )
    .scanDirectory( '/another/path' )
        .for      ( /\.js$/i        ) // provided to both paths above?
    .doSomethingElse()

这就是为什么我正在寻找一个可能有更成熟的想法来实现这个目标的库:)

5 个答案:

答案 0 :(得分:2)

这篇文章讨论了JS中的执行类型,最后有相关库的链接

在JavaScript中执行

您在JS中有两种类型的执行:

  • 同步 - 在调用时发生的事情
  • 异步 - 在当前代码运行完毕后发生的事情,也就是您所说的延迟。

同步

同步,您可以将操作和参数推送到队列结构,并使用.run命令运行它们。

您可以执行以下操作:

var chain = function(){
   var queue = []; // hold all the functions

   function a(param){
       //do stuff, knowing a is set, may also access other params functions set
   }
   return {
       a:function(someParam){
          queue.push({action:a,param:someParam});
          return this;
       },
       ... // more methods
       run:function(){
           queue.forEach(function(elem){ // on each item
               elem.action.apply(null,param);//call the function on that item
           });
       }
   };
}

当你调用run时,这将执行队列中的所有函数,语法类似于

chain().a(15).a(17).run();

异步

您只需设置超时,就不需要使用类似.run的内容。

var chainAsync = function(){        //不需要队列

   function a(param){
       //do stuff, knowing a is set, may also access other params functions set
   }

   return {
       a:function(someParam){
          setTimeout(a,0,someParam);
          return this;
       },
       ... // more methods
   };
}

用法类似于

chain().a(16).a(17);

一些问题:

  • 如果要在函数之间共享参数,可以将它们存储在对象本身的某个位置(除队列外还有var state。)

  • 它是同步或异步。您无法通过上下文检测其中一个。正在为ES6构建解决方法。

更多资源

答案 1 :(得分:0)

请注意,您一定会找到一个全面的解决方案。

看起来你正在寻找一种通用的解决方案来解决那些需要已经融入库中的问题。我的意思是,我确信有些库具有这种功能,但它们不会自动地在其他库上挂钩(假设它们已经专门为你想要定位的库的正确版本实现了覆盖,可能)。

但是,在某些情况下,您可能需要查看Stream.js库,这可能涵盖了足够的数据相关案例,以使您感兴趣:

答案 2 :(得分:0)

我不知道是否有用于构建此类方法的库,但您可以自己轻松构建该功能。基本上,它将是一个具有setter方法和一个execute函数的设置对象(在您的情况下为defer)。

function Scanner() {
    this.dirs = [];
    this.recurse = false;
    this.search = "";
    this.cache = false;
    this.to = "";
    this.name = "";
}
Scanner.prototype = {
    scanDirectory: function(dir) {
        this.dirs.push(dir);
        return this,
    },
    recursively: function() {
        this.recurse = true;
        return this;
    },
    for: function(name) {
        this.search = name;
        return thsi;
    },
    cache: function() {
        this.cache = true;
        return this;
    },
    provideTo: function(service) {
        this.to = service;
        return this;
    },
    as: function(name) {
        this.name = name;
        return this;
    },
    defer: function() {
        // now, do something with all the given settings here
    },
    doSomethingElse: function() {
        // now, do something else with all the given settings here
    }
};

这是构建fluent interface的标准方法。当然,你也可以创建一个辅助函数,你传递一个方法名称到设置的映射,如果它太冗长就会为你编写方法: - )

答案 3 :(得分:0)

您需要一个队列来维护方法链的异步和同步。

这是一个使用jQuery.queue的实现,我为一个项目做了:

function createChainable(options) {
    var queue = [];

    var chainable = {

        method1 : function () {
            queue.push(function(done){
                // code here
                done();
            });
            return chainable;
        },

        exec1 : function () {
            queue.push(function(done){
                // code here
                done();
            });
            $.queue(ELEMENT, QUEUE_NAME, queue).dequeue(QUEUE_NAME);
            return chainable;
        }
    };

    return chainable;
}

答案 4 :(得分:-3)

正如@Jordan Doylecomment中所说的那样:

只需返回this

因此,对象中的每个方法都应该返回return语句中的对象,以便您可以链接另一个方法。

例如:

var obj = new (function(){

   this.methOne = function(){
      //...
      return this;
   }

   this.methTwo = function(){
      //...
      return this;
   }

   this.methThree = function(){
      //...
      return this;
   }

})();

//So you can do:
obj.methOne().methTwo().methThree();