异步/等待的明确性,带有睡眠示例

4

我试图通过以下实现掌握async/await,但它并没有按预期工作。

    public static async sleep(ms: number): Promise<void> {
        await Utilities._sleep(ms);
    }

    private static _sleep(ms: number): Promise<{}> {
        return new Promise((resolve: Function) => setTimeout(resolve, ms));
    }

_sleep会在n毫秒后解析promise,而await应该在此期间sleep

但是我的下面的测试失败了。

it("should sleep for 500 ms", ()=> {
    const date1 = (new Date()).getTime();
    Utilities.sleep(500);
    const date2 = (new Date()).getTime();
    chai.expect(date2 - date1).to.least(500);
})

带有消息

 sleep should sleep for 500 ms FAILED
    AssertionError: expected 2 to be at least 500

我的理解是:sleep将等待直到来自_sleep的承诺被解决(根据setTimeout的设置,它将在500毫秒后解决)。 编辑 mocha中的测试框架。

6
当您调用 Utilities.sleep(500); 时,在测试中您不需要等待结果。详情请见 https://github.com/jasmine/jasmine/issues/923。 - Igor
“async”函数只是返回一个Promise的函数,它的调用并不能神奇地将异步代码变为同步代码。目前问题不太清楚,是关于“async”函数还是测试?如果是前者,那么测试示例就不相关了;如果是后者,那么问题就有些缺失,甚至没有提到您使用的测试框架是哪个。所以这个问题是关于测试还是关于异步/等待的呢? - Estus Flask
@estus 我知道这不是魔法,因此我正在尝试学习一些我不理解的东西。问题是如何在JavaScript中实现“sleep”。 - harishr
值得注意的是,你的 sleep() 方法与 _sleep() 相比没有任何优势。它们都返回一个 Promise,在 ms 毫秒后解决,并且可以互换使用。 - user3432422
@user3432422 很好的观点,非常感谢您提供的信息。 - harishr
2个回答

7

您没有等待您的sleep()调用(正如用户@igor在您的问题评论中所描述的):

简化版本:

async function sleep(ms: number) {
    await _sleep(ms);
}

function _sleep(ms: number) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

console.time('start')
sleep(500).then(() => {
    console.timeEnd('start')
})

// If your test runner supports async:
it("should sleep for 500 ms", async () => {
    const date1 = (new Date()).getTime();
    await sleep(500);
    const date2 = (new Date()).getTime();
    chai.expect(date2 - date1).to.least(500);
})

但是我在 sleep 中使用了 await,这与在 test 中使用的 await 有什么不同? - harishr
当调用sleep(500)时,您还需要使用await - unional
在测试中添加了awaitawait Utilities.sleep(500)),但仍然无法正常工作。 - harishr
@estus不是很糟糕,我已经免责声明"如果测试运行器支持异步"。 :) - unional
它也可以是 jest,其语法相同。 - unional
显示剩余3条评论

2

只有await等待,在调用点await也仅在async函数内有效。用法:

await promise;

async函数视为返回承诺的函数的更好写法,它只是语法糖。
不可能隐藏在同步函数调用内部嵌套的异步语义,而不改变调用它的所有函数的语义,使它们全部异步。请考虑这些内容是否会在此事件循环中或稍后返回。
如果你想知道为什么异步语义不是默认值,请阅读为什么协程在Web上不起作用

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接