我已经在我的页面上组装了一个小工具,并且在大多数情况下它似乎起作用,但当我尝试将其插入Q.js
时,我有一点奇怪的行为。
通常,据我所知,你可以用这种方式调用函数。
Q(manager.tasks.init)
.then(manager.tasks.start)
.then(manager.tasks.fulfill)
.then(manager.tasks.finish);
但是我似乎无法做到这一点,而是我必须调用它们并像函数一样显式地调用它们。像这样。
Q(manager.tasks.init())
.then(manager.tasks.start())
.then(manager.tasks.fulfill())
.then(manager.tasks.finish());
这里可以看到完整的代码;
现在,我可以使用括号,但我不明白为什么它正在这样做。我想了解这里发生了什么,所以任何信息都会受到赞赏。
答案 0 :(得分:3)
记录我们在上述评论和对我的回答的评论中所经历的一些内容......
上述任何一种解决方案都没有真正正确编码。第一个问题有问题,因为this
在Q调用回调时不会设置属性。
当你这样做时:
Q(manager.tasks.init)
.then(manager.tasks.start)
.then(manager.tasks.fulfill)
.then(manager.tasks.finish);
Q会调用这些方法,但this
指针不会像你想要的那样设置为manager.tasks
。所以,当你在方法中做这样的事情时:
$(this).trigger("init:begin");
然后this
不会成为你想要的东西,它将抛出异常并停止执行。您可以通过以下方式解决这个问题:
Q(manager.tasks.init.bind(manager.tasks))
.then(manager.tasks.start.bind(manager.tasks))
.then(manager.tasks.fulfill.bind(manager.tasks))
.then(manager.tasks.finish.bind(manager.tasks));
这将导致this
设置为manager.tasks
。或者,您可以删除这些方法中this
的任何用法,以便它们成为静态方法(这是您选择做的)。
第二个没有按照它应该传递给.then()
的函数引用。
当你这样做时:
Q(manager.tasks.init())
.then(manager.tasks.start())
.then(manager.tasks.fulfill())
.then(manager.tasks.finish());
JS解释器立即调用您的函数(当您将()
放在最后时会发生什么)并将这些函数的返回值传递给每个.then()
行。那不是你想要的。 .then()
想要传递一个函数引用,以便promise库可以在以后执行该函数。在您的情况下,您的函数返回的承诺不是您应该传递给.then()
的承诺。
因为在这些方法中没有实际的异步操作,所以这似乎可以正常工作,因为它按顺序调用了操作,但只要你在其中任何一个实际上解决了承诺的异步操作,它就行不通了正确。
对于perform方法的问题,您需要使用在reduce操作中创建名为results
的延迟/保证。我也改变它以在setTimeout()
之前运行reduce,因为它对我来说似乎有点干净(更容易理解)。您正在设置要完成的所有工作,然后在setTimeout()
中通过解决链中的第一个延迟来开始工作。
然后,它返回从list.reduce()
操作返回的链式承诺,并使用链式.then()
处理程序来知道何时输出"fulfill:end"
消息。
manager.tasks.fulfill = function () {
// alert the task manager that we're beginning this phase
$(manager.tasks).trigger("fulfill:begin");
// create a placeholder for the result of all of the items in the list
var results = Q.defer();
setTimeout(function(){
// resolve the first defer we created to
// let the `.then()` chain start to run
results.resolve();
}, 6000);
// now add all then `.then()` onto the results
// these functions won't run yet because the first defer has not yet resolved
return list.reduce(function(i, f) {
return i.then(f);
}, results.promise).then(function() {
// alert the task manager that we're ending this phase
// after all the callback promises have finished
$(manager.tasks).trigger("fulfill:end");
});
};
我认为如果你的回调返回这样的承诺,.enqueue()
问题将得到解决:
manager.tasks.enqueue(function(deferred){
return function(){
setTimeout(function(){
console.log('test');
deferred.resolve();
}, 3000);
return deferred.promise;
};
});
如果这是我,我可能会更改.enqueue()
实现,以便它处理promise的返回(因为它是创建它的那个),但这里的快速解决方案就是确保你的回调在执行时返回承诺。
您可以在此处查看jsFiddle的推导http://jsfiddle.net/jfriend00/JxJVs/,并实施这些更改,生成您在JPEG中显示的确切输出。