操作异步函数的两点建议
这儿是工具函数
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 住