5

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

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

这就是为什么我正在寻找一个可能有更成熟的想法的图书馆来实现这一点:)

4

5 回答 5

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 构建解决方法。

更多资源

于 2013-06-05T20:43:39.900 回答
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
    }
};

这是构建流畅界面的标准方法。当然,您也可以创建一个辅助函数,向该函数传递一个方法名到设置映射,如果它太长,它会为您编写方法:-)

于 2013-06-05T20:53:53.040 回答
0

请注意,您一定会为此找到一个全方位的工作解决方案。

看起来您正在寻找一个通用解决方案来解决需要已经融入库的东西。我的意思是,我确定有些库具有此功能,但它们不会自动挂接到其他库上(期望它们是否专门为您想要定位的正确版本的库实现了覆盖)。

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

于 2013-06-05T20:28:59.177 回答
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;
}
于 2013-06-06T16:53:34.063 回答
-3

正如@Jordan Doyle在他的评论中所说:

刚回来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();
于 2013-06-05T20:29:56.927 回答