简体   繁体   English

如何清除 JavaScript 中异步函数的超时

[英]How can I clear timeout for an asynchronous function in JavaScript

Let me be very clear so as to avoid confusion.让我说得很清楚,以免混淆。 I have a sleep function (below) which timeouts for as many millisecond as I specify.我有一个睡眠功能(如下),它超时了我指定的毫秒数。

function sleep(ms) 
{
    return new Promise(resolve => setTimeout(resolve, ms));
}

Now in another function beginTest() I called sleep for some millisecond let say 5000 ms.现在在另一个函数 beginTest() 中,我调用了 sleep 几毫秒,比如说 5000 毫秒。

async function beginTest()
{
    await sleep(5000);
}

I have a separate function which gets executed when a button is clicked.我有一个单独的函数,当单击按钮时会执行该函数。 I want the function to clear the timeout whenever the button is clicked before completion of 5000 ms.我希望该函数在 5000 毫秒完成之前单击按钮时清除超时。 I understand that after 5000 ms clicking the button should not affect anything as the promise has already been resolved.我知道在 5000 毫秒后点击按钮应该不会影响任何事情,因为承诺已经得到解决。

document.getElementById("reactTimeClick").onmousedown = function()
{
    cleartimeOut(); // Clear timeout of above function
}

It's pretty simple to do as you propose with a "cancellation token" via which the "sleep timeout" can be cancelled:按照您的建议,使用“取消令牌”可以取消“睡眠超时”,这非常简单:

// don't do this
function sleep(ms, cancellationToken) {
    return new Promise(resolve => function() {
        let timeoutRef = setTimeout(resolve, ms);
        cancellationToken.cancel = function() {
            clearTimout(timeoutRef);
        };
    });
}

However that will not, in itself, cause the sleep promise to depart from its pending state and the promise chain (or awaiting statements) stemming from sleep() will not be informed of the cancellation.然而,这本身不会导致睡眠承诺脱离其pending状态,并且源自sleep()的承诺链(或等待语句)不会被通知取消。 Progress will hang.进度将挂起。

This shortcoming can be overcome, again with a cancellation token, but this time one that allows the sleep() promise to be rejected, as follows ...这个缺点可以克服,再次使用取消令牌,但这次允许sleep()承诺被拒绝,如下所示......

// do this
function sleep(ms, cancellationToken) {
    return new Promise((resolve, reject) => function() {
        cancellationToken.cancel = function() {
            reject(new Error('sleep() cancelled'));
        };
        setTimeout(resolve, ms));
    }
}

... and in the caller, use as follows: ...并在调用者中,使用如下:

async function beginTest() {
    try {
        const token = {};
        const promise = sleep(5000, token);
        $('#cancelButton').on('click', token.cancel); // jQuery example, or similar in POJS
        await promise;
        // ... test code ...
        // ... return whatever;
    }
    catch(error) {
        console.log(error.message);
        // If button was clicked before the 5000 ms has expired, 
        // and no other error has been thrown, 
        // then the log will show "sleep() cancelled".
        throw error; // rethrow error to keep beginTest's caller informed.
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM