使用 async / await 实现 setTimeout 的同步写法

发布时间: 2021-01-29 16:43:22 作者: 大象笔记

在 tampermonkey 的很多实际使用场景中,需要在模拟点击之后,等待界面变化,或者数据返回,此时就需要用到 setTimeout。但是如果是一系列的点击等待,就需要进行 setTimeout 嵌套,或者 setTimeout 时间进行倍数增长,代码可读性非常低。

所以,我想找一种 setTimeout 同步的写法,以提高代码的可维护性。

测试代码

(function() {
    'use strict';

    function wait(ms) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log("Done waiting");
                resolve(ms)
            }, ms)
        })
    }

    (async () => {
        console.log("Starting...")
        await wait(5000);
        console.log("Ended!")

        for (var i = 0, len = 6; i < len; i++) {
            console.log("loop " + i);
            await wait(2000);
        }

    })();

    console.log("end");
})();

在 tampermonkey 中的运行结果:

Starting...
end
Done waiting
Ended!
loop 0
Done waiting
loop 1
Done waiting
loop 2
Done waiting
loop 3
Done waiting
loop 4
Done waiting
loop 5
Done waiting

完全符合预期,以后写 setTimeout 就不用嵌套那么多层了。

Uncaught SyntaxError: await is only valid in async function

注意 await 只能在 async 函数中使用,否则会报错:

Uncaught SyntaxError: await is only valid in async function

async / await 的字面意思

async / await 的使用方法

参考 MDN 上的示例:

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);
  // expected output: "resolved"
}

asyncCall();

为何要使用 Promise

A Promise is an object representing the eventual completion or failure of an asynchronous operation.

await 的下一行代码,只有当 await 等待的 promise 被 resolve,才能被执行。

async / await 的兼容性问题

async / await 是 ES7 进入的,即 ECMAScript 17。

参考

我是一名山东烟台的开发者,联系作者