做了一个大的重构,这是最后一个工作示例,带有进度监控。
现在是重要的部分。
- 在调用 resolve 之后,JQuery deferreds 不执行任何进度回调(有一个例外)。在您的示例中(没有 setTimeout),延迟立即解决,没有机会运行进度。
- 在我们在最终的 Deferred 上触发 enything之前,执行所有回调的挂钩,尤其是进度回调。这是通过在我们填充它的触发器之后将最终的 Deferred(现在是信标)传递给执行函数来实现的。
- 我重构了 API,所以要执行的函数是延迟不可知的。
- 该解决方案在 memo.then 函数内部使用了一个局部(对于 reduce 迭代器函数)Deferred 的闭包,以继续执行链。
编辑:我忘记了你的第一个问题。这种行为是通过闭包(“x”函数中的 dfd 变量)实现的。
函数“x”立即返回(在触发一个现在可以处理的通知事件之后,因为执行链的所有延迟都已创建,并且“executePromiseQueueSync”的完成、失败、进度挂钩已被挂钩)。
此外,setTimeout 的函数在闭包中“关闭”dfd,因此尽管“x”已返回,它仍可以访问该变量。“then”调用通过创建与第一个链接的下一个延迟来继续。
在 JS VM 产生后(它没有其他事情要做), setTimeout 触发它的关联函数,该函数(通过闭包)可以访问“关闭”的 dfd 变量。Deferred 已解决,链可以继续。
EDIT2:这是一个重构版本,增加了对长时间执行、延迟支持的函数的支持,它们通知调用者他们的进度。
EDIT3:这是另一个版本,没有下划线绑定和 jq-ui 进度条示例。
顺便说一句,这对于复杂的应用程序初始化例程来说是一个非常好的主意。
来源(第一版)
function executePromiseQueueSync(queue, beacon){
var seed = $.Deferred(),
le = queue.length,
last;
beacon.notify(0);
last = _.reduce(queue, function(memo, ent, ind){
var df = $.Deferred();
df.then(function(){
console.log("DBG proggie");
beacon.notify((ind+1)/le*100);
});
console.log("DBG hook funk "+ind);
memo.then(function(){
console.log("DBG exec func "+ind);
ent.funct.apply(null, ent.argmnt);
df.resolve();
});
return df.promise();
}, seed.promise());
last.then(function(){
beacon.resolve(100)
});
seed.resolve(); // trigger
return beacon.promise();
}
function x(){
// do stuff
console.log("blah");
}
var promisesQueue = [],
beacon = $.Deferred();
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
function monTheProg(pct)
{
console.log('progress '+pct);
}
// first hook, then exec
beacon.then(function(){
console.log('success');
}, function(){
console.log('failure');
}, monTheProg);
// do the dance
executePromiseQueueSync(promisesQueue, beacon)