简单 jquery 延迟队列

Simple jquery deferred queue

我有一个方法 foo(param) 是同步的。

我希望可以自由调用 foo(param) 而不执行实际的 foo() 调用,直到稍后发生特定事件。

它看起来很适合延迟/承诺,但我一定是做错了什么,因为超时没有任何效果。

日志方法return应该承诺吗?

var log = function(message) {
    $('#log').append('<p>' + message + '</p>');
};

$(function() {
 
    var q = new $.Deferred();
    
    q.then(log("1"));
    q.then(log("2"));
    q.then(log("3"));
    q.then(log("4"));
    q.then(log("5"));
    q.then(log("6"));
    q.then(log("7"));
    
    setTimeout(function(){
        q.resolve();
    }, 10000);
    
    
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="log"></div>

是的,你说 q.then(log("...")) 的台词应该说 q.then(function() { log("...") })

您的 log 函数没问题,但您的代码当前的工作方式是您 已经调用它 并将其 return 值传递给 then函数。这就是为什么您需要创建一个新函数,延迟将在稍后解析时调用该函数。

当您执行 q.then(log("1")); 时,它试图获取“log("1")”的函数值以传递给 then 函数。这是评估功能,这就是为什么您在控制台中看到它们而不是您想要的原因。

像这样包装它们应该可以解决您的问题:

q.then(function() {
    log("1")
});

你应该写什么完全取决于"until a particular event later"的意思。

可以有两种解释。

用户事件: 用户事件(在浏览器中)类似于 'click' 或 'mouseover'。它的出现 不是 由 javascript/jQuery 中的任何内容决定的,它可能永远不会发生。但是,通过附加事件处理程序,您可以确保 if/when 事件确实发生,并采取预先确定的行动方案。

日志序列将建立如下:

$(selector).on('eventType', function() {
    log("1");
    log("2");
    log("3");
    log("4");
    log("5");
    log("6");
    log("7");
});

异步响应:异步响应是在异步进程完成时发生的事件。它的发生取决于 (a) 正在启动的 aync 进程和 (b) 它的最终完成。同样,完成可能永远不会发生,但比用户事件更有保证。一个写得很好的 aync 进程应该保证完成(成功或不成功)。

日志序列将建立如下:

asyncProcess().then(function() {
    log("1");
    log("2");
    log("3");
    log("4");
    log("5");
    log("6");
    log("7");
});

如您所见,在这两种情况下,log() 语句都是简单的顺序代码行。

在任何一种情况下都没有必要建立 Promise 链,因为 log() 本身是同步的。但是,如果你想探究Deferreds/Promises的本质,那么异步版本可以这样写:

asyncProcess()
    .then(log.bind(null, "1"))
    .then(log.bind(null, "2"))
    .then(log.bind(null, "3"))
    .then(log.bind(null, "4"))
    .then(log.bind(null, "5"))
    .then(log.bind(null, "6"))
    .then(log.bind(null, "7"));

// Note that .then() takes functions as arguments so `.bind(...)` is necessary to establish functions with bound-in arguments, without actually executing `log("1"); log("2"); log("3");` etc at the time the .then() chain is established.

只要 asyncProcess() return 承诺 :

  • 已经解决
  • 在未来的某个时候解决,

.then() 链中指定的函数将执行,并且 1,2,3,4,5,6,7 将出现在您的日志中。

在最简单的形式中,asyncProcess 可能如下所示:

function asyncProcess() {
    return $.when(); //return a resolved promise
}

DEMO

为了稍微冒险一点,并为承诺链提供一些用途,您可以探索其传输数据的能力。

首先,将 asyncProcess() 改编为 return 一个通过作为参数传递给函数的数字解决的承诺:

function asyncProcess(n) {
    return $.when(n);//return a promise resolved with the valie 1
}

然后,修改log()接受一个数字n,记录它,然后return n+1:

function log(n) {
    $('#log').append('<p>' + n + '</p>');
    return n + 1;
}

并按如下方式调整承诺链:

asyncProcess(1)
    .then(log)
    .then(log)
    .then(log)
    .then(log)
    .then(log)
    .then(log)
    .then(log);

这里,对 .bind() 的需求消失了,因为在没有任何绑定参数的情况下使用了原始 loglog 每次调用中的参数由上一次调用的 return 值提供。

DEMO