gpt4 book ai didi

javascript - 如何同步 JavaScript 回调?

转载 作者:可可西里 更新时间:2023-11-01 02:04:24 24 4
gpt4 key购买 nike

我使用 JavaScript 进行开发已经有一段时间了,但我还是一名牛仔式开发人员,因为同步 JavaScript 的回调是经常困扰我的事情之一。

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

代码示例:

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

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

建议的解决方案:

在循环开始时启动一个计数器来保存循环的长度,并且每个回调都会递减该计数器。当计数器达到 0 时,执行 myFunc2。这实际上是为了让回调知道它是否是序列中的最后一个回调,如果是,则在完成时调用 myFunc2。

问题:

  1. 代码中的每个这样的序列都需要一个计数器,到处都有无意义的计数器不是一个好习惯。
  2. 如果您还记得经典同步问题中的线程冲突,当多个线程都在同一个 var 上调用 var-- 时,就会出现不良结果。 JavaScript 中是否也会发生同样的情况?

终极问题:

有没有更好的解决方案?

最佳答案

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

如果你想序列化异步任务,然后是一个完成回调,你可以使用这个辅助函数:

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

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

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

这是循环回调函数:

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

传递的第一个参数是一个将执行下一个任务的函数,它应该传递给您的异步函数。第二个参数是值数组的当前条目。

让我们假设异步任务是这样的:

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

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

然后,启动整个过程:

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

Demo

要将它们并行化,您需要一个不同的函数:

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

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

你的循环函数将是这样的(只有参数名称改变):

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

Demo

关于javascript - 如何同步 JavaScript 回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15963590/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com