我想知道如何实现这种方法链式:
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
有可能吗?
答案 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!');
非常感谢!