jQuery 1.5带来了新的Deferred对象和附加方法.when、.Deferred和. _deferred。
对于那些以前没有使用过. deferred的人,我已经为它注释了源代码。
这些新方法的可能用途是什么,我们如何将它们纳入模式?
我已经阅读了API和源代码,所以我知道它是做什么的。我的问题是我们如何在日常代码中使用这些新特性?
我有一个简单的缓冲区类示例,它按顺序调用AJAX请求。(上一个结束后下一个开始)。
/* Class: Buffer
* methods: append
*
* Constructor: takes a function which will be the task handler to be called
*
* .append appends a task to the buffer. Buffer will only call a task when the
* previous task has finished
*/
var Buffer = function(handler) {
var tasks = [];
// empty resolved deferred object
var deferred = $.when();
// handle the next object
function handleNextTask() {
// if the current deferred task has resolved and there are more tasks
if (deferred.isResolved() && tasks.length > 0) {
// grab a task
var task = tasks.shift();
// set the deferred to be deferred returned from the handler
deferred = handler(task);
// if its not a deferred object then set it to be an empty deferred object
if (!(deferred && deferred.promise)) {
deferred = $.when();
}
// if we have tasks left then handle the next one when the current one
// is done.
if (tasks.length > 0) {
deferred.done(handleNextTask);
}
}
}
// appends a task.
this.append = function(task) {
// add to the array
tasks.push(task);
// handle the next task
handleNextTask();
};
};
我正在寻找. deferred和.when的演示和可能的用法。
看到. _deferred的例子也很不错。
链接到新的jQuery。Ajax源代码的例子是作弊。
我特别感兴趣的是,当我们抽象出一个操作是同步完成还是异步完成时,可以使用哪些技术。
ehyds的答案将不起作用,因为它缓存了响应数据。它应该缓存jqXHR,这也是一个Promise。
下面是正确的代码:
var cache = {};
function getData( val ){
// return either the cached value or an
// jqXHR object (which contains a promise)
return cache[ val ] || $.ajax('/foo/', {
data: { value: val },
dataType: 'json',
success: function(data, textStatus, jqXHR){
cache[ val ] = jqXHR;
}
});
}
getData('foo').then(function(resp){
// do something with the response, which may
// or may not have been retreived using an
// XHR request.
});
Julian d的答案是正确的,是一个更好的解决方案。
这里是一个与ehynd的答案略有不同的AJAX缓存实现。
正如fortuneRice的后续问题所指出的,如果请求在其中一个返回之前执行,ehynd的实现实际上并不能阻止多个相同的请求。也就是说,
for (var i=0; i<3; i++) {
getData("xxx");
}
如果“xxx”的结果之前没有被缓存过,很可能会导致3个AJAX请求。
这可以通过缓存请求的deferred而不是结果来解决:
var cache = {};
function getData( val ){
// Return a promise from the cache (if available)
// or create a new one (a jqXHR object) and store it in the cache.
var promise = cache[val];
if (!promise) {
promise = $.ajax('/foo/', {
data: { value: val },
dataType: 'json'
});
cache[val] = promise;
}
return promise;
}
$.when(getData('foo')).then(function(resp){
// do something with the response, which may
// or may not have been retreived using an
// XHR request.
});
我能想到的最佳用例是缓存AJAX响应。以下是Rebecca murphy关于该主题的介绍帖子的修改示例:
var cache = {};
function getData( val ){
// return either the cached value or jqXHR object wrapped Promise
return $.when(
cache[ val ] ||
$.ajax('/foo/', {
data: { value: val },
dataType: 'json',
success: function( resp ){
cache[ val ] = resp;
}
})
);
}
getData('foo').then(function(resp){
// do something with the response, which may
// or may not have been retrieved using an
// XHR request.
});
基本上,如果值已经被请求过一次,然后立即从缓存中返回。否则,AJAX请求将获取数据并将其添加到缓存中。当美元/。然后不关心这些;您需要关心的是使用响应,在这两种情况下,响应都传递给.then()处理程序。jQuery.when()将非promise /Deferred处理为Completed,立即执行链上的.done()或.then()。
当任务可能异步操作,也可能不异步操作时,延迟非常适合,并且您希望从代码中抽象出该条件。
另一个使用$的真实例子。当助手:
$.when($.getJSON('/some/data/'), $.get('template.tpl')).then(function (data, tmpl) {
$(tmpl) // create a jQuery object out of the template
.tmpl(data) // compile it
.appendTo("#target"); // insert it into the DOM
});