如何同步JavaScript回调? [英] How to synch JavaScript callbacks?

查看:156
本文介绍了如何同步JavaScript回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JavaScript开发已经有一段时间了,但是net却是一个牛仔开发者,因为总是困扰我的很多事情之一是同步JavaScript的回调。

I've been developing in JavaScript for quite some time but net yet a cowboy developer, as one of the many things that always haunts me is synching JavaScript's callbacks.

我将描述一个通用场景,当这个问题被提出时:我有一堆操作通过一个for循环执行多次,每个操作都有一个回调。在for循环之后,我需要执行另一个操作,但是如果来自for循环的所有回调都完成,这个操作只能成功执行。

I will describe a generic scenario when this concern will be raised: I have a bunch of operations to perform multiple times by a for loop, and each of the operations has a callback. After the for loop, I need to perform another operation but this operation can only execute successfully if all the callbacks from the for loop are done.

程式码范例:


for ... in ... {
  myFunc1(callback); // callbacks are executed asynchly
}

myFunc2(); // can only execute properly if all the myFunc1 callbacks are done


建议的解决方案:

在循环开始时启动一个计数器,持有循环的长度,每个回调函数递减计数器。当计数器命中0时,执行myFunc2。这实质上是让回调函数知道它是否是序列中的最后一个回调函数,如果是,则在完成后调用myFunc2。

Initiate a counter at the beginning of the loop holding the length of the loop, and each callback decrements that counter. When the counter hits 0, execute myFunc2. This is essentially to let the callbacks know if it's the last callback in sequence and if it is, call myFunc2 when it's done.

问题:


  1. 代码中每个这样的序列都需要一个计数器,并且无处不在的计数器不是一个好习惯。

  2. 如果你记得在经典同步问题中线程如何发生冲突,当多个线程都在同一个var上调用var时,会发生不希望的结果。

终极问题:

有更好的解决方案吗?

推荐答案

好消息是JavaScript是单线程的;这意味着解决方案通常适用于共享变量,即不需要互斥锁。

The good news is that JavaScript is single threaded; this means that solutions will generally work well with "shared" variables, i.e. no mutex locks are required.

如果你想序列化异步任务,可以使用这个帮助函数:

If you want to serialize asynch tasks, followed by a completion callback you could use this helper function:

function serializeTasks(arr, fn, done)
{
    var current = 0;

    fn(function iterate() {
        if (++current < arr.length) {
            fn(iterate, arr[current]);
        } else {
            done();
        }
    }, arr[current]);
}

第一个参数是需要在每次传递中传递的值的数组,第二个参数是一个循环回调(如下所述),最后一个参数是完成回调函数。

The first argument is the array of values that needs to be passed in each pass, the second argument is a loop callback (explained below) and the last argument is the completion callback function.

这是循环回调函数:

function loopFn(nextTask, value) {
    myFunc1(value, nextTask);
}

传递的第一个参数是执行下一个任务的函数,意味着要传递给你的异步函数。第二个参数是您的数组数组的当前条目。

The first argument that's passed is a function that will execute the next task, it's meant to be passed to your asynch function. The second argument is the current entry of your array of values.

让我们假设asynch任务看起来像这样:

Let's assume the asynch task looks like this:

function myFunc1(value, callback)
{
  console.log(value);
  callback();
}

打印值,然后调用回调;简单。

It prints the value and afterwards it invokes the callback; simple.

然后,设置整个动作:

serializeTasks([1,2, 3], loopFn, function() {
    console.log('done');
});

演示

要并行化,您需要一个不同的功能:

To parallelize them, you need a different function:

function parallelizeTasks(arr, fn, done)
{
    var total = arr.length,
    doneTask = function() {
      if (--total === 0) {
        done();
      }
    };

    arr.forEach(function(value) {
      fn(doneTask, value);
    });
}

你的循环函数将是这个(只有参数名称改变) p>

And your loop function will be this (only parameter name changes):

function loopFn(doneTask, value) {
    myFunc1(value, doneTask);
}

演示

这篇关于如何同步JavaScript回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆