Javascript:如何实现异步函数队列(没有库)

时间:2013-08-22 17:48:01

标签: javascript animation asynchronous callback

我一直在搜索Google和SO,但由于某种原因,我很难将这些脑筋包裹起来。需要强调的是,我不想加载像JQuery这样的库,因为我不需要大部分库。虽然我可以使用动画库,但我已经构建了我自己需要的几个函数(其中一些甚至不是你在库中找到的标准动画),所以我不是确定那些甚至会有所帮助。事实上,我可以轻易地将这个问题标题为“如何 - 异步函数队列”,因为它不是特定于动画。

在我的搜索中,我遇到了Promises的想法,但这似乎比我需要的更多。

我得到了一般原则 - 你有一个使用setInterval / setTimeout的异步函数,并且给定正确的条件,你清除间隔(如果适用)并运行回调:

function callback() {
    alert('It was just a sales call... Now where were we?');
}
function anim() {
    var i = 0,
        interval = setInterval( function() {
            // do something with the current value of i
            if (i === 100) {
                clearInterval( interval );
                callback();
            }
            i++;
        }, 50);
}

当然,如果通过将'callback'作为anim()的参数使其可重用,这会更好。但是,我真正希望能够做到的是:

var populateDialog = new Queue([
    {fn: anim, args: ['height','300px',1500]},
    {fn: type, args: [input.value, outputDiv]},
    {fn: highlight}
]);
populateDialog.start();

将调用第一个函数,当它完成时,将调用队列数组中的下一个项目。问题是,虽然队列本身可以很容易地按顺序调用函数,但它需要知道当前函数的状态何时“完成”才能继续。

我如何设计我想要添加到队列的任何函数,以便a)发布其状态(以及如何让队列检测到?)或b)是否可以接受来自队列的回调?我猜测前者会涉及某种自定义事件系统,而后者会更容易,看起来像:

function name(callback, param1, param2, ... paramX) {
    // setTimeout or setInterval some stuff, then call the callback argument
}

其中回调始终是第一个参数,因此可以添加任意数量的其他参数。但就像我说的那样,我在整理这些问题的过程中遇到了麻烦,因此我将非常感谢您的全面解释/任何替代方案!

修改

我想出的队列可以在my follow-up question找到。

1 个答案:

答案 0 :(得分:3)

  

我如何设计我想添加到队列中的任何函数,以便a)发布其状态(以及如何检测队列?)我猜它会涉及某种自定义事件系统

完全。

这将是Promises的概念 - 您的动画函数返回一个对象,队列可以在该对象上附加“完成”侦听器。如果您不想使用其中一个many many libraries,您还可以实现自己的系统(简单的pub-once / sub-often模式)。请查看How is a promise/defer library implemented?(特别是我的答案的first two版本)以获取一些灵感......

然后队列将像

一样工作
var promise = queue[i].fn.apply(null, queue[i].args);
promise.then(function() {
    i++;
    // … "recurse"
});
  

b)可以接受来自队列的回调吗?这会更容易,看起来像:   function name(callback, param1, param2, ... paramX) {…}其中回调始终是第一个参数,因此可以添加任意数量的其他参数。

完全。或者最后一个参数,这是更常见的。看看apply Function method是否有动态数量的参数调用函数。

队列就像是

function step(i) {
    function callback() {
        step(i+1); // "recurse"
    }
    if (i < queue.length)
        queue[i].fn.apply(null, queue[i].args.concat(callback));
    // else: all done
}
  

但就像我说的那样,我在围绕所有这一切缠绕我的大脑时遇到了麻烦,所以非常感谢您的全面解释/任何替代方案!

嗯,你已经把它钉了 - 除了你概述的两种方法之外别无选择。 promise方法更有效,对动画函数的可变参数更有效,而回调方法更简单。