【问题标题】:Asynchronous Javascript Confusion异步 Javascript 混乱
【发布时间】:2021-05-03 17:10:40
【问题描述】:

我对 Javascript 还很陌生,写这篇文章是我的头脑,所以如果我有任何错误,请纠正我。

据我所知,异步函数允许其他进程在后台运行,然后在函数完成后,它返回一个可以解决或拒绝的承诺。此外,由于异步函数中的进程不会按设定的顺序运行,我们可以使用 await 关键字来停止执行,直到进程完成。

然而,让我感到困惑的是两者在代码执行上的差异

function f1() {
  //do stuff
}

function f2() {
  //do stuff
}

function f3() {
  //do stuff
}

async function asyncFunc() {
  f1()
  f2()
  f3()
}

asyncFunc()

还有这个:

async function asyncf1() {
  //do stuff
}

async function asyncf2() {
  //do stuff
}

async function asyncf3() {
  //do stuff
}

function f() {
  asyncf1()
  asyncf2()
  asyncf3()
}

f()

????? (除了第一个示例返回一个承诺这一显而易见的事实)

在同步函数中调用异步函数与在异步函数中调用同步函数是一回事吗?它们都产生相同的输出吗?如果是这样,哪一个比另一个更受欢迎?

【问题讨论】:

  • 好吧,你的代码中没有等待......所以它会是一样的。首选什么取决于手头的任务。
  • 异步函数允许其他进程在后台运行,然后在函数完成后,它返回一个可以解决或拒绝的承诺。
  • 研究建议 - 1. async 函数的实际作用。 2. JavaScript 中的多线程。具体来说,它是如何选择加入的,并且大多数代码仍然是单线程运行的。
  • 第一个有效,第二个无效。是否使用异步功能通常不是您的决定。异步函数必须从异步函数(或正确处理结果承诺的异步感知站点)调用

标签: javascript function asynchronous


【解决方案1】:

要理解的关键是async 函数是使用promises 的语法糖。 async 函数和承诺都不会在后台发生任何事情。它们让您等待已经在后台发生的事情并做出反应(例如计时器或 HTTP 操作完成)。

async 函数在第一个 awaitreturn 之前是同步的。 (这样它就可以启动它然后等待的任何异步过程。)此时,它返回一个承诺,该承诺将根据awaited 和/或者你返回什么。

await 暂停函数的逻辑,直到/除非承诺是 awaited 解决。 (如果你使用await value,而value 不是thenable [类似promise 的东西],那么你实际上是在做await Promise.resolve(value)。)

您没有显示 asyncFuncX 函数的任何内容,但除非它们 await 某些东西,否则它们是完全同步的。

您可能会发现my answer from a couple of days ago 也很有用。

【讨论】:

  • 直到第一个 await 之前,我才意识到 async 函数是同步的。我的心智模式是,他们基本上总是被派去执行一项任务。直到,谢谢你:)
  • @AKX - :-) 很高兴!
  • @Jackbaklava(好吧,或者其他任何人)我在我最近一本书的第 8 章和第 9 章中详细介绍了 Promises 和 async 函数JavaScript:新玩具。如果您有兴趣,请在我的个人资料中链接。
  • @AKX 如果你对C++20 coroutines有任何了解的话,async 的 JavaScript 实现相当于在状态机中为initial_suspend() 挂起点使用suspend_never 类型,意思是JavaScript 中的异步函数是 eagerly 启动的,而不是 lazily 启动的。相反,JavaScript 中的生成器函数相当于使用 suspend_always 类型作为 initial_suspend() 暂停点,因为它们是延迟启动的,并且仅在调用 generator.next() 后才开始执行。
  • 哦!所以它们是相同的,因为我没有使用任何等待。这解释了一切。谢谢! :) @T.J.Crowder
【解决方案2】:

在同步函数中调用异步函数与在异步函数中调用同步函数是一样的吗?

一点也不。 async 函数由 JavaScript 执行环境安排在单独的 microtasks 中执行(在第一个 awaitas explained in TJ Crowder's answer 之后),在同步函数的流程之外。这意味着async函数(可以)在调用同步函数被return退出后继续运行。

如果你运行下面的sn-p,你可以看到输出是inoutf1f2f3,即使f函数显然看起来是@ 987654333@,f1f2f3out

(该示例有一个额外的await noop() 来真正实现异步。)

async function noop() {}

async function asyncf1() {
  await noop();
  console.log('f1');
}

async function asyncf2() {
  await noop();
  console.log('f2');
}

async function asyncf3() {
  await noop();
  console.log('f3');
}

function f() {
  console.log('in');
  asyncf1();
  asyncf2();
  asyncf3();
  console.log('out');
}

f()

相反,在async 函数中调用同步函数可以工作,但会阻止该任务,并且由于 JavaScript 引擎是单线程的 JavaScript 代码,它会阻止所有其他 async 任务“同时执行” "也是。

它们都产生相同的输出吗?

他们没有。 (或者,好吧,这是一个哲学问题。如果函数不返回任何东西或不做任何事情,那么是的,结果可能被认为是相同的。)

【讨论】:

  • @T.J.Crowder 澄清。
  • "如果你运行下面的sn-p,你可以看到输出是in, out, f1, f2, f3" 只有在this 具体例子。例如,如果asyncf2 中没有await,那么您将进入 -> f2 -> out -> f1 -> f3
猜你喜欢
  • 1970-01-01
  • 2020-09-14
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多