async/await 相关代码改造


输出以下代码运行结果,为什么?如果希望每隔 1s 输出一个结果,应该如何改造?注意不可改动 square 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const list = [1, 2, 3]
const square = num => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * num)
}, 1000)
})
}

function test() {
list.forEach(async x=> {
const res = await square(x)
console.log(res)
})
}
test()

分析: 由于forEach是不能阻塞的,所以会同时输出1、4、9,如果需要每隔1秒输出一个结果,需要将并行改成串行,使await强制阻塞。

  • 方法一: 使用for循环

    1
    2
    3
    4
    5
    6
    7
    async function test() {
    for (let i = 0; i < list.length; i++) {
    let x = list[i]
    const res = await square(x)
    console.log(res)
    }
    }
  • 方法二:使用for of语句

    1
    2
    3
    4
    5
    6
    async function test() {
    for (let x of list) {
    const res = await square(x)
    console.log(res)
    }
    }
  • 方法三:利用promise的链式调用

    1
    2
    3
    4
    5
    6
    let promise = Promise.resolve()
    function test(i = 0) {
    if (i === list.length) return
    promise = promise.then(() => square(list[i])).then(console.log)
    test(i + 1)
    }
  • 方法四:使用reduce

    1
    2
    3
    4
    5
    list.reduce(async (_, x) => {
    await _
    const res = await square(x)
    console.log(res)
    }, undefined)
  • 方法五:直接嵌套个setTimeout

    1
    2
    3
    4
    5
    6
    7
    8
    function test() {
    list.forEach(async x => {
    setTimeout(async () => {
    const res = await square(x)
    console.log(res)
    }, 1000 * x)
    })
    }
  • 方法六:基于闭包

1
2
3
4
5
6
7
8
function test() {
;(async () => {
for await (let num of list) {
const res = await square(num)
console.log(res)
}
})()
}

 评论