JavaScript——异步函数

笔记 · 05-27 · 65 人浏览

Promise

  1. 创建 Promise (执行器函数的同步执行):

    • 当你使用 new Promise((resolve, reject) => { ... }) 创建一个 Promise 实例时,传递给构造函数的执行器函数 (executor function) 会被立即同步执行
    • 这个执行器函数接收两个参数:resolvereject。这两个参数本身也是函数,由 JavaScript 引擎提供,用于改变 Promise 的状态。
    • 在执行器函数内部,你通常会启动一个异步操作(比如网络请求 Workspace、定时器 setTimeout、文件读写等)。
  2. resolve, reject会使Promise的状态发生改变

    • 如果操作成功,执行器函数内部应该调用 resolve(value)。这会将 Promise 的状态从 pending 变为 fulfilled (已兑现),并且 value 会作为 Promise 的结果值。
    • 如果操作失败,执行器函数内部应该调用 reject(reason)。这会将 Promise 的状态从 pending 变为 rejected (已拒绝),并且 reason (通常是一个 Error 对象) 会作为 Promise 的拒绝原因。
  3. 然后可以注册回调函数 (.then(), .catch(), .finally())

    • 这三个方法都可以接收函数参数执行注册回调函数
    • 这些方法可以在 Promise 落定之前或之后调用

      • 如果调用时 Promise 还是 pending,回调函数会被存储起来,等待 Promise 落定后再执行。
      • 如果调用时 Promise 已经 fulfilledrejected,相应的回调函数会被调度为异步执行(通常是放入微任务队列)。
  4. 回调函数的异步执行 (微任务队列 Microtask Queue)

    • 即使 Promise 的 resolvereject立即执行了,通过 .then(), .catch(), 或 .finally() 注册的回调函数也不会立即同步执行。这些回调会被放入微任务队列 (Microtask Queue) 中。
    • 在当前同步代码块执行完毕后,会检查微任务队列。如果队列中有任务,会依次取出并执行,直到微任务队列清空。然后才会去处理宏任务队列 (Macrotask Queue,如 setTimeout 的回调、I/O 事件等)

async/await

  • async的函数返回Promise,这类函数里可以使用await关键字。
  • await 关键字用于等待一个 Promise 落定。它会暂停 async 函数的执行,直到 await 后面的 Promise fulfilled (然后返回其结果值) 或 rejected (然后抛出其拒绝原因,可以被 try...catch 捕获)。
  • async可以主动返回Promise,但是这个Promise前带不带await有点区别:

    • 如果是直接return new Promise()那么这个Promise会被直接返回
    • 如果return await new Promise()这个await会等待后面的Promise落定
  • async不主动返回Promise

    async function foo() {
    return 'Hello, World!';
    }

    这里返回的值会自动成为一个已解决的Promise的值。

    foo().then(message => console.log(message)); // 输出 'Hello, World!'

    例题

    leetcode 2621. 睡眠函数
    https://leetcode.cn/problems/sleep/description/

async function sleep(millis) {
    return new Promise(resovle => {
        setTimeout(resovle, millis)
    })
}

/**
 * let t = Date.now()
 * sleep(100).then(() => console.log(Date.now() - t)) // 100
 */

在调用sleep(100).then(() => console.log(Date.now() - t))时,执行器函数执行异步函数setTimeout(resovle, millis),在等待millis秒后,resovle执行,返回的或者Promise状态改变,此时使用.then方法注册回到函数() => console.log(Date.now() - t)立即执行

Theme Jasmine by Kent Liao