对象键的异步/等待分配:它是并发的吗?

Posted

技术标签:

【中文标题】对象键的异步/等待分配:它是并发的吗?【英文标题】:Async / await assignment to object keys: is it concurrent? 【发布时间】:2017-10-17 16:02:38 【问题描述】:

我知道这样做:

const resultA = await a()
const resultB = await b()
// code here

有效

a().then( resultA => 
   b().then( resultB => 
      // code here
   )
)

基本上,a() 运行 然后 b() 运行。我嵌套它们以表明 resultA 和 resultB 都在我们的范围内;但是这两个功能都没有立即运行。

但是这个呢:

const obj = 
  result1: await a(),
  result2: await b()

a() 和 b() 是否同时运行?

供参考:

const asyncFunc = async (func) => await func.call()
const results = [funcA,funcB].map( asyncFunc )

我知道这里funcAfuncB 会同时运行。

奖金

你将如何表示对象分配

const obj = 
  result1: await a(),
  result2: await b()

使用then/回调?


更新:

@Bergi 在这个答案中是正确的,这是按顺序发生的。要分享一个很好的解决方案,让一个对象同时进行这项工作,而不必将数组中的对象拼凑在一起,也可以使用Bluebird,如下所示

const obj2 = Bluebird.props(obj)

http://bluebirdjs.com/docs/api/promise.props.html

【问题讨论】:

您的“供参考”示例存在语法错误(因此具有误导性)。如果使用await,则必须使箭头函数async,然后很明显它们可能会同时运行,因为它们是单独的函数评估。 感谢您的理解,已更正。 请注意,JS函数可能会触发异步进程并发运行,但JS函数本身并不是多线程同时执行意义上的并发运行。 【参考方案1】:

不,每个await 都会停止执行,直到承诺完成,即使是在表达式中。它们是否恰好是同一语句的一部分并不重要。

如果你想并行运行它们,并且只等待一次它们的结果,你必须使用await Promise.all(…)。在你的情况下,你会写

const [result1, result2] = await Promise.all([a(), b()]);
const obj = result1, result2;

您将如何使用then / 回调来表示对象分配?

每个等待值都有临时变量。每个await 转换为一个then 调用:

a().then(tmp1 => 
  return b().then(tmp2 => 
    const obj = 
      result1: tmp1,
      result2: tmp2
    ;
    return …
  );
)

如果我们想学究气,就必须拆开对象创建:

const tmp0 = ;
a().then(tmp1 => 
  tmp0.result1 = tmp1;
  return b().then(tmp2 => 
    tmp0.result2 = tmp2;
    const obj = tmp0;
    return …
  );
)

【讨论】:

你是对的!我刚刚写完测试代码来尝试使用 setTimeout 上面的代码,它确实是按顺序运行的。【参考方案2】:

a() 和 b() 是否同时运行?

不,它们按顺序运行。

相当于

a()
.then(result1 => b())
  .then(result2 => (result1, result2))

【讨论】:

以上是关于对象键的异步/等待分配:它是并发的吗?的主要内容,如果未能解决你的问题,请参考以下文章

线程和异步的分别与联系

异步和多线程的关系

异步和多线程的关系

想玩转JAVA高并发,这些概念你必须懂

python-并发并行同步异步同步锁

python 同步异步,并发并行,同步锁