【问题标题】:Javascript: How to implement a queue of async functions (without libraries)Javascript:如何实现异步函数队列(没有库)
【发布时间】:2013-08-25 14:17:15
【问题描述】:

我一直在搜索 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);
}

当然,如果你让它可重用,通过将“回调”作为 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找到。

【问题讨论】:

    标签: javascript animation asynchronous callback


    【解决方案1】:

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

    没错。

    这就是Promises 的概念——您的动画函数返回一个对象,队列可以在该对象上附加“完成”侦听器。如果您不想使用many many libraries 之一,您也可以实现自己的系统(一个简单的pub-once/sub-often 模式)。看看How is a promise/defer library implemented?(尤其是我的答案的firsttwo 修订版)以获得一些灵感……

    然后队列会像这样工作

    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 方法更可靠,更适用于动画函数的可变参数,而回调方法更简单。

    【讨论】:

    • 是的,我意识到回调通常是最后一个参数,这就是为什么它首先让我感到奇怪。您能否编辑您的答案以显示我需要如何让每个功能访问它?我知道如何使用 apply - 我可以轻松地将回调添加到参数数组。我是否需要访问参数和 .pop() 最后一项(回调)?
    • 另外,我已经掌握了这些概念。我理解这一切背后的概念。我似乎无法将其转换为实际代码!呵呵。这两种方法哪个更好?优点和缺点......哪个更容易?老实说,Promises 的想法让我很困惑。无论我阅读了多少次关于它的各种文章,我都无法弄清楚那个傻瓜!
    • 感谢您的补充解释,尽管我仍然不确定如何实际实施它,直到我坐下来自己弄清楚。查看我编辑的帖子,看看我是否已经很好地实现了它。
    • 哦,好吧...我不知道我应该这样做。正如帖子的标题所暗示的那样,我想要一个完整的排队方法,因为我在其他地方找不到这个。虽然你的回答让我上路了,但我觉得这不足以标记。仍然有足够的问题可以解决我发布的内容,我觉得它仍然适合“操作方法”标题。不过,如果您真的认为我应该提出一个新问题,我可以这样做。
    • 是的,我认为你的新问题基本上是不同的。虽然可能是同一个主题,但问题的风格已经发生了巨大的变化(从“如何设计队列”、“如何进行回调”到“我的代码有问题吗”和“队列应该有哪些功能”)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 2011-05-19
    • 2017-01-03
    • 2016-12-20
    相关资源
    最近更新 更多