使用“.delay”启用链式方法

时间:2010-08-06 13:34:22

标签: javascript

我想知道如何实现这种方法链式:

var foo = function(){};

foo.prototype = {
 say : function(s){
        alert(s);
        return this;
       },
 delay : function(ms){
          var _this = this;
          setTimeout(function(){
           return _this;
          }, ms);
         return this; // If I omit this, there will be an error.
         }
}

var bar = new foo();
bar.delay(2000).say('hello'); // this will immediately alert 'hello'.

我想这样用:

bar.delay(2000).say('hello'); // in 2 sec. say 'hello'.

不喜欢这样:

bar.delay(2000, function()...); // it's not a chained method

有可能吗?

2 个答案:

答案 0 :(得分:3)

是的,但是你不能通过在delay()之后从ms函数返回来实现它 - 对setTimeout的调用是异步的,所以立即返回。要实现此效果,您必须实现自己的排队系统。一些代码:

var queue = new Queue();

function delay(ms) {
    queue.enqueue("delay");
    setTimeout(function() {
        popQueue(true);
    }, ms);

    return this;
}

function say(s) {
    queue.enqueue(function() {
        alert(s);
    });
    popQueue();

    return this;
}

function popQueue(removeDelay) {
    if (removeDelay) {
        if (queue.peek() == "delay") queue.dequeue();
    }
    while (!queue.isEmpty() && queue.peek() != "delay") {
        (queue.dequeue())();
    }
}

本质上,代码通过修改每个“可延迟”的函数来工作,因此它将自身插入到队列中,而不是立即执行。 delay()函数将一个字符串作为“阻塞”项插入队列,以防止添加到队列中的函数执行。然后,您可以使用超时在给定的毫秒数后从队列中删除该块。

上面的代码只是让您了解延迟是如何实现的,但不是一个有效的例子。显然你需要某种Queue implementation,或者你可以修改它以使用数组,或者你可以实现自己的SelfExecutingQueue对象来自动继续执行函数(直到它遇到一个非函数对象)排队或出队后立即不需要您手动拨打popQueue()等等......

答案 1 :(得分:0)

感谢您的建议,我成功了!这是代码。

var foo = function(){};

foo.prototype = {
 say : function(s){
  Queue.enqueue(function(){
   alert(s);
  });
  Queue.flush();
  return this;
 },
 delay : function(ms){
  Queue.enqueue('delay:' + ms);
  return this;
 }
}

Queue = {
 entries : [],
 inprocess : null,
 enqueue : function(entry){
  Queue.entries.push(entry);
 },
 flush : function(){
  if(Queue.inprocess) return;
  while (Queue.entries.length){
   var entry = Queue.entries.shift();
   if(entry.toString().indexOf('delay:') !== -1){
    var ms = Number(entry.split(':')[1]);
    Queue.inprocess = setTimeout(function(){
     Queue.inprocess = null;
     Queue.flush();
    }, ms);
    return;
   }
   entry();
  }
 }
}

我准备了一个Queue对象来管理函数的条目。 有了这个,我可以玩一个方法链:

var bar = new foo();
bar.delay(2000).say('Hello, ').delay(3000).say('world!');

非常感谢!