你了解 await 吗?
在工作中,我发现在执行一个 await aaa?.bbb
语句时,就算 aaa 为 null,也会异步执行后面的代码,而不是同步,这引起了我的好奇心探索它
宏任务队列和微任务队列
在 TypeScript 中,await 关键字用于等待一个异步操作的完成,并暂停当前函数的执行,直到该操作完成并返回结果。尽管在某些情况下,await 可能会在 Promise 已经完成的情况下立即执行,但它仍然会异步执行。
这是因为 await 语句的行为是基于 JavaScript 中的异步编程模型,即使用 Promises 和 async/await 来处理异步操作。无论 Promise 的状态是已完成、进行中还是已拒绝,await 都会将其封装在一个微任务中,并将控制权交还给事件循环,以便其他任务有机会执行。
这种行为确保了 JavaScript 的单线程执行模型,避免了阻塞主线程,同时允许其他异步操作和事件在 await 语句期间进行处理。即使 Promise 已经完成,await 仍然会在事件循环的下一个微任务队列中执行,以确保代码的一致性和可预测性。
总之,尽管在某些情况下 await 可能会立即执行,但它仍然被设计为异步执行,以保持 JavaScript 的事件驱动模型,并确保代码的可靠性和一致性。
await 之后的代码是否是下一帧?
在 JavaScript 中,事件循环由多个任务队列组成,包括宏任务队列和微任务队列。宏任务队列包含一些异步任务,例如定时器回调、事件回调(如点击事件、网络请求完成等)等。而微任务队列用于保存 Promise 的回调函数、MutationObserver 的回调函数以及 process.nextTick 等。
在事件循环的每一轮中,当一个宏任务完成后,会检查微任务队列是否有待执行的任务。如果存在微任务,那么会依次执行所有的微任务,直到微任务队列为空,然后再执行下一个宏任务。
所以,下一个微任务队列并不一定是下一帧,而是在当前任务执行完成后,在事件循环的下一轮中执行的微任务队列。微任务的执行时机相对更早,因为它们在当前任务执行完成后立即执行,而不需要等待下一帧。
请注意,"下一帧"通常与渲染相关,而微任务队列是 JavaScript 引擎内部的任务调度机制,与渲染过程不直接关联。