javascript 是否可以通过异步循环存在可变并发问题

问题描述

let mutableObject = {};
for( ...loop over wtv...) {
  const res = await someAsyncFunc();
  if(!mutable[res.someKey]) {
      mutable[res.someKey] = {}
  }
  mutable[res.someKey][res.other] = res.value;
}

res.someKey 对许多 res 是通用的,问题是,是否有可能在某个时候 mutable[res.someKey] 被检测为空,实际上它正在由循环中的另一个 res 填充。这可能导致重置( mutable[res.someKey] = {})并跳过其他填充 res 操作。

换句话说,这件事件可能吗?

=> loop1 !mutable[res.someKey] 为空 ...

=> loop2 !mutable[res.someKey] 为空,让我们重置并填充!

=> loop1 ... ,让我们重置和填充 => 我们失去了重置的 loop2 动作

我认为它可以在下一个循环之前执行整个循环,但我有一些疑问。

我希望它足够清楚让我知道,提前致谢。

解决方法

如果我理解正确的话,这是不可能的。

JavaScript 通常是单线程的(也有例外,但您没有具体说明,所以我认为您的情况没有什么特别之处)。

在 JavaScript 中,所有代码都在事件内部执行。这些事件被排入事件队列。队列中的事件总是在队列中的下一个事件执行之前完全执行,因为只有一个线程可以执行它们。

使用 async-await 时,从代码中看有点困难,但主要内容仍然保持不变。

我总是这样看:

enter image description here

async-await 在 await 处将函数“切割”成多个部分,但这些部分本身总是在其他任何事情发生之前完整执行。

当函数启动时,下面的代码被执行而不能被不同的事件中断。

let mutableObject = {};
for( ...loop over wtv...) { // first iteration
  someAsyncFunc(); // someAsyncFunc is executed but does not "return" yet

然后第一个“事件”因为await而结束。

当 someAsyncFunc() 返回的 Promise 解决时。它将继续:

  const res = // result is written from someAsyncFunc
  if(!mutable[res.someKey]) {
      mutable[res.someKey] = {}
  }
  mutable[res.someKey][res.other] = res.value;
}
for( ...loop over wtv...) { // next iteration
  someAsyncFunc();

这部分也不能被不同的事件中断,这意味着在 res 被设置为下一次调用 someAsyncFunc() 之间发生的一切都是原子发生的。

因此,在此期间另一个循环无法填充 mutable[res.someKey]

进一步阅读: