2010-08-06 45 views
3

我想知道如何實現這種方法鏈風格啓用鏈接方法:使用「.delay」

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 

可能嗎?

回答

3

是的,這是可能的,但你不能通過在ms之後從delay()函數返回 - 對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,或者你可以修改它來使用數組,或者你可以實現你自己的對象,在排隊或出隊之後立即自動繼續執行函數(直到它遇到非函數對象),而不需要你手動撥打popQueue()等...

+0

謝謝!我看到這個概念。所以似乎我需要使用類似隊列的「包裝」功能對我的原始代碼進行大的修改。 [隊列實現]鏈接看起來非常有趣。我會稍後閱讀。 – martin 2010-08-06 14:42:49

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!'); 

非常感謝!