在Web世界中,异步编程是一个不可或缺的部分。大约一年前,与一位同事合作,他试图在JavaScript中创建类似于TPL(任务并行库)的任务结构,以支持诸如ContinueWith、Wait、Result、WhenAny等典型的TPL功能。他提到了jQuery的一个特性,叫做“Deferred”和“Futures”。坦白说,在过去的一年里,并没有对此进行太多思考,直到偶然听到一位新同事提到“Deferred”和“Futures”,意识到需要深入研究一下。
事实上,关于这个话题有很多资料,所以在这里展示的内容可能不会是最新的或创新的,但如果之前没有听说过,它至少可以激发兴趣去了解更多。
在展示一个示例之前,让先谈谈jQuery Deferred。在jQuery中,一个Deferred对象是一个异步活动,可以通过注册的回调来信号它的成功或失败。自jQuery 1.5以来,内置的jQueryAjax调用已经在使用Deferred对象。
可以在这里阅读更多关于Deferred的信息:,在这里可以使用诸如When、Then、Done等管道函数,这很棒。这意味着可以构建这些的整个管道,并且只在整个链“Done”时调用回调,或者继续做其他事情。
但真正的力量(至少在看来)来自于可以自己创建$.Deferred对象。这里有一个简单的示例,它执行一个jQuery Get调用,然后是一个超时。创建了一个Deferred,它只会在这两个都完成时运行回调。
<script>
(function($) {
doIt();
function getData() {
return $.get('/Dummy.htm');
}
function timeout(x) {
var dfd = $.Deferred();
setTimeout(function() {
dfd.resolve();
}, x);
return dfd.promise();
}
function doIt() {
$.when(getData(), timeout(2000))
.done(function(ajaxResult, timeOutResult) {
$('#mainDiv').append('The animation AND the AJAX request are both done!');
alert('AJax result is \r\n :' + ajaxResult);
});
}
})(jQuery);
</script>
需要特别注意的关键部分是:创建了一个新的Deferred对象,在实际工作时解析Deferred对象,并且返回一个将从Deferred对象中执行工作的Promise。这是一个非常简单的使用Deferred的示例,但这可以用于各种新颖的事情,比如: