操作异步函数的两点建议

这儿是工具函数

async function sleepMs(n: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, n);
  });
}

async function asyncFunc() {
  await sleepMs(500)
}

async function randomAsyncFunc() {
  await sleepMs(Math.random() * 1000)
}

忠告一: 异步函数如果有顺序要求, 则最好 await 之

// 此处, 你能幸运地得到顺序打印的 1 2
async function main() {
  asyncFunc().then(() => {
    console.log(1)
  })

  asyncFunc().then(() => {
    console.log(2)
  })
}

// 此处, 只有老天才能知道 1 2 的打印顺序了
async function main() {
  randomAsyncFunc().then(() => {
    console.log(1)
  })

  randomAsyncFunc().then(() => {
    console.log(2)
  })
}

// 因此: 如果对顺序有要求, 最好 await 之
async function main() {
  await randomAsyncFunc().then(() => {
    console.log(1)
  })

  await randomAsyncFunc().then(() => {
    console.log(2)
  })
}

忠告二: 谨慎在异步函数中操作引用变量

async function anotherAsyncFunc() {
  const arr = []

  sleepMs(500).then(() => {
    // 在异步函数中操作引用变量需要谨慎 (这是错误用法)
    arr.push(42)
  })

  return arr
}

async function main() {
  const res = anotherAsyncFunc()

  // 这儿打印的结果是 []
  console.log(res)

  await sleepMs(1000)
  // 这儿打印的结果却是 [42]
  console.log(res)
}

先解释一下上面的代码, 就是由于 arr 是引用变量, 所以, 返回值 res 开始是空数组, 等睡了 500 ms 后, arr.push(42) 被执行, 导致返回值被修改, 此后 arr 变成了 [42]

你可能会说, 谁会写出这么傻的代码, 我只能说有则改之无则加勉, 操作异步函数需要谨慎, 最好是等待其 await, 如果特殊场合不允许, 则尽量别在其内操作指针或执行有顺序要求的动作, 一定要这么做的话, 确保自己能 hold 住

如非特别声明,本站作品均为原创,遵循【自由转载-保持署名-非商用-非衍生 创意共享 3.0 许可证】。

对于转载作品,如需二次转载,请遵循原作许可。