异步会使其内部的所有内容异步吗?

zha*_*hou 2 javascript node.js async-await

根据MDN,

异步函数声明定义了一个异步函数

我理解它,因为该函数将被视为异步过程,就像setTimeout某个数据库请求一样。例如,在下面的示例中,该过程应在数字之间的某个位置输出“ main”。

let func2 = async () => {
   for (let i = 0; i < 51; i ++) {
       console.log(i);
   }
}

(async () => {
    func2();
    console.log("main");
})()
Run Code Online (Sandbox Code Playgroud)

但是,就像整个过程是同步的一样,“ main”总是在最后被控制台。我理解错了什么?

如果同步代码仍然是同步的,那么目的是async什么?只允许await在其内部提供一些幻想的方法来返回Promise

jfr*_*d00 7

异步会使其内部的所有内容异步吗?

不,不是的。函数中的代码仍将同步运行,并在运行时阻止事件循环。

如果同步代码仍处于同步状态,那么异步的目的是什么?只允许在其中等待并提供某种幻想的方式来返回Promise?

是的,主要是针对await

但是,在某些情况下,它会自动用承诺包装代码,这很有用。例如,它会自动捕获所有抛出的异常,并将其转变为被拒绝的承诺。有时这很有用。有关其他有用性的示例,请参见本文的“错误处理”部分:JavaScript的Async / Await导致Promises Away消失的6个原因

但是,async关键字的主要功能是定义一个可以使用的功能await。这就是ES7的设计师决定进行await工作的方式。

仅供参考,如果await函数中有一个等待诺言的内容,则将导致该函数在的点早返回await。它将在那时返回并返回承诺。您正在等待的操作将已经开始,并且直到解决了等待的诺言之后,该功能的其余部分才会执行。因此,使用可以await使某些代码稍后执行。但是,就像之前的代码一样await,即使该函数在await解析后恢复运行,该函数中的Javascript仍将保持同步和阻塞状态(直到另一个await或直到return)。

将其包装在Promise中并检测其完成时间.then()将在.then()调用处理程序时推迟到事件循环的下一个刻度为止。因此,这.then()会稍有延迟,因为您将其包装在promise中,然后使用.then(),但是代码运行的时间不变。它仍然是同步和阻塞的。

在Javascript中,获取同步代码并使之异步的唯一方法是:

  1. 在另一个进程中运行它,并使用进程间通信来传达结果。

  2. 使用本机线程或某些其他OS异步接口执行实际工作的本机代码加载项中重写代码,然后从您的加载项提供到Javascript的异步接口(通常是一个返回承诺或通过以下操作通知完成的接口)回调)。现在这是node.js等异步功能的fs.readFile()工作。他们有一个本机代码实现,该实现立即返回,然后在实现中使用本机线程,并通过回调通知完成。

  3. 使用一些node.js附加组件为您完成其中的一些工作。 有一些旨在提供线程的加载项。

  4. 在节点版本10.5+中使用node.js线程,并按其要求进行限制。这是一篇有关以下主题的文章:Node 10.5.0中的线程:实用介绍


Mar*_*yer 6

不,异步函数内的主体在调用时运行,但在await表达式中暂停。如果没有 to await,该函数将像普通函数一样运行,但它返回一个承诺。

但是,如果有await,则暂停执行并继续事件循环。当等待的承诺在当前事件循环完成后的某个时间解决时,它会从停止的地方开始。例如,比较何时在此处记录“main”与您的示例。

let func2 = async () => {
    console.log("Start")
    for (let i = 0; i < 10; i ++) {
        if(i == 5) {
            await new Promise(resolve => setTimeout(resolve, 200))
        }
        console.log(i);
    }
 }
 
 (async () => {
     func2().then(() => console.log('done'));
     console.log("main");
 })()
Run Code Online (Sandbox Code Playgroud)

考虑async函数的另一种方式是考虑它们与生成器的关系。我喜欢将其await视为一种yield. 例如,我们唯一需要的身体变化func2,以获得相同的行为被换awaityield

function* func2() {
  console.log("Start")
  for (let i = 0; i < 10; i++) {
    if (i == 5) {
      yield new Promise(resolve => setTimeout(resolve, 0))
    }
    console.log(i);
  }
  return "done"
}

let gen = func2()
gen.next().value.then(() => console.log(gen.next().value))

console.log("main")
Run Code Online (Sandbox Code Playgroud)

async/await只是使这对于常见用例更容易和更直观。