基本概念
事件循环的全部意义在于有许多互不影响的微任务(因此默认情况下没有影响)。
首先链接微任务;有回调,然后是 Promises (then/catch),然后是 async/await API。最后两个可以被认为只是回调概念之上的语法糖。没有添加“功能”,而是使用不同的语法以更简单、更优雅的方式实现相同的东西(Pyhilosophicaly)。
事件循环在每个循环中执行所有排队的微任务并重复。除非您有阻塞代码(并且await 不被视为阻塞),否则您的事件循环永远不会停止,因此其他任务不会受到影响。
您正试图从其他语言中的实际阻塞代码的角度来理解await。
恕我直言,您首先需要深入了解回调是如何工作的,然后研究 Promises(作为一种使回调不那么混乱的工具),然后是 async/await(作为使 Promises 更漂亮的语法)。但请记住,底层系统是相同的:调用函数的函数得到处理的函数最终会被调用)。
具体问题
当一个promise被创建时开始运行
是的,但不是。承诺不会运行,承诺只是您通过部分代码收到的合同,该部分代码将用于通知您结果。所以 promise 没有运行,是在你请求执行任务后为你创建的意思。
因此,通常如果向您处理了一个承诺,就会有一些“正在运行”的东西。但是Promise 的用法可能不同,可能会有一些“等待”。
promise 与任务的执行无关,因此它无法启动或停止它。
如果我对结果不感兴趣,是否需要等待承诺?
不,您不需要这样做。但请记住,不处理承诺异常已被弃用,并可能导致系统故障。您应该始终处理(或冒泡)异常。
如果存在未处理的 Promise 拒绝,则会失败。在同步代码中,这相当于未捕获的抛出错误。直到现在(-ish)未捕获的承诺拒绝被容忍,但没有一个很好的理由。 Node 正在将它们视为与冒泡到顶部的任何其他错误相同的处理方式。
VLAZ
您只考虑使用async/await 的承诺,但底层Promise api 是.then() 和.catch()。使用此 API,您可以以“即发即弃”的方式使用 Promise:
async function Do() {
await before();
asyncDbCall().catch(err => console.error(err))
await after();
}
在此示例中,您不等待asyncDbCall(),但.catch(err => console.error(err)) 仍将导致错误被记录(在将来的某个时间,甚至可能在Do() 完成之后)。
或者您可以将执行分支到其他异步执行,举个复杂的例子:
async function Do() {
await before();
// This will execute AFTER before() & only if before() succeeded
asyncDbCall()
.then(async value => {
// This will execute after `asyncDbCall()` and only if it succeeded
await something(value);
// We reach here after `something()` and only if succeeded
})
.catch(err => {
// This will execute if `asyncDbCall()` fails of IF ANYTHING
// within `async value => {}` fails
console.error(err);
})
// This will execute AFTER before() and only if before() succeeded and
// asyncDbCall() call (but not Promise) succeeded
await after();
}
Await 实际上阻塞了异步函数的执行
Await 停止 async 函数(因此还有任何正在等待该函数的函数),但无论如何都不会影响事件循环。