如何使用jQuery延迟?

2022-08-30 00:15:11

jQuery 1.5 带来了新的 Deferred 对象和附加方法 .when.推迟._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源代码是作弊。

我特别感兴趣的是,当我们抽象出一个操作是同步还是异步完成时,可以使用哪些技术。


答案 1

我能想到的最好的用例是缓存AJAX响应。以下是Rebecca Murphey关于该主题的介绍性帖子中的一个修改示例:

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 请求将提取数据并将其添加到缓存中。/ 不关心这些;您需要关心的就是使用响应,在两种情况下都会传递给处理程序。jQuery.when() 将非承诺/延迟处理为已完成,立即执行链上的任何或。$.when.then.then().done().then()

延迟非常适合于任务可能以异步方式运行或可能不异步运行的情况,并且您希望从代码中抽象出该条件。

使用帮助程序的另一个真实示例:$.when

$.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

});

答案 2

下面是 AJAX 缓存的实现与 ehynd 的答案略有不同的实现

正如 fortuneRice 的后续问题所指出的那样,如果请求在其中一个请求返回之前执行,则 ehynd 的实现实际上并没有阻止多个相同的请求。那是

for (var i=0; i<3; i++) {
    getData("xxx");
}

如果之前尚未缓存“xxx”的结果,则很可能导致 3 个 AJAX 请求。

这可以通过缓存请求的延迟而不是结果来解决:

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.
});