我如何运行带有超时机制的异步函数

发布于 2025-01-11 00:06:48 字数 765 浏览 0 评论 0原文

runTaskWithTimeout()之后, 在“任务超时错误发生”后如何成功打印“任务终于”?

谢谢。

async function runTaskWithTimeout() {
    try {
        const timeout = setTimeout(() => {
            console.log('task timeout error happen')
            throw new Error('timeout error happened')
        }, 2000)
        console.log('task start')

        await wait(3000);
        /** assume this is async function*/

        clearTimeout(timeout);
        console.log('task complete')
    } catch (error) {
        console.log('catch error', error.message);
    } finally {
        console.log('task finally')
    }
}

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

after runTaskWithTimeout(),
how can i print 'task finally' successfully after 'task timeout error happen'?

thanks.

async function runTaskWithTimeout() {
    try {
        const timeout = setTimeout(() => {
            console.log('task timeout error happen')
            throw new Error('timeout error happened')
        }, 2000)
        console.log('task start')

        await wait(3000);
        /** assume this is async function*/

        clearTimeout(timeout);
        console.log('task complete')
    } catch (error) {
        console.log('catch error', error.message);
    } finally {
        console.log('task finally')
    }
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

撞了怀 2025-01-18 00:06:48

您可以使用 轻松设置超时Promise.race。这是一个函数(与您的 wait 函数类似)在延迟后解决承诺,但与 wait 不同的是,它拒绝承诺并包含以下错误给定的消息:

const timeout = (ms, message) => {
    return new Promise((_, reject) => {
        setTimeout(() => {
            reject(new Error(message));
        }, ms);
    });
};

然后在 runTaskWithTimeout 中,您将超时与实际工作进行竞争:

async function runTaskWithTimeout() {
    console.log("Running");
    try {
        await Promise.race([
            timeout(3000), // 3000 = the maximum time to wait
            (async () => {
                // ...do the real work, modelled here as `wait`...
                await wait(2000);
            })()
        ]);
        console.log("task complete")
    } catch (error) {
        console.log("catch error", error.message);
    } finally {
        console.log("task finally")
    }
}

Promise.race 用您传递给它的第一个 Promise 的结果来结算它的 Promise。因此,如果实际工作在超时之前完成(或失败),那就是 Promise.race 的承诺结果。如果超时发生在实际工作完成之前,则超时是 Promise.race 的结果。

实时示例使用 timeoutwait 的随机值,因此有时超时会在工作完成之前发生,有时则不会:

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

const timeout = (ms, message) => {
    return new Promise((_, reject) => {
        setTimeout(() => {
            reject(new Error(message));
        }, ms);
    });
};

async function runTaskWithTimeout() {
    console.log("Running");
    try {
        // Just for the purposes of example, let's make it random which
        // comes first:
        const timeoutLength = Math.floor(Math.random() * 1000);
        const waitLength    = Math.floor(Math.random() * 1000);
        await Promise.race([
            timeout(timeoutLength),
            (async () => {
                // This is the real work
                await wait(waitLength);
            })()
        ]);
        console.log("task complete")
    } catch (error) {
        console.log("catch error", error.message);
    } finally {
        console.log("task finally")
    }
}

document.getElementById("run").addEventListener("click", () => {
    runTaskWithTimeout();
});
<input type="button" id="run" value="Run">

注意:以上只是一个草图。在完整的实现中,您需要一种方法让“实际工作”知道超时已经发生,以便它可以停止正在做的任何事情。您可能想使用 AbortController AbortSignal (或者如果您不执行网络代码,则在您的环境中使用等效项)。并且您可能希望 runTaskWitHTimeout 返回“实际工作”的实现值(在上面它可以通过返回来自 wait Promise.race 的值来完成)在非错误分支中)。

You can readily do a timeout with Promise.race. Here's a function that (like your wait function) settles a promise after a delay, but unlike wait, it rejects the promise with an error containing the given message:

const timeout = (ms, message) => {
    return new Promise((_, reject) => {
        setTimeout(() => {
            reject(new Error(message));
        }, ms);
    });
};

Then in runTaskWithTimeout, you race that timeout with the actual work:

async function runTaskWithTimeout() {
    console.log("Running");
    try {
        await Promise.race([
            timeout(3000), // 3000 = the maximum time to wait
            (async () => {
                // ...do the real work, modelled here as `wait`...
                await wait(2000);
            })()
        ]);
        console.log("task complete")
    } catch (error) {
        console.log("catch error", error.message);
    } finally {
        console.log("task finally")
    }
}

Promise.race settles its promise with the result of the first promise you pass it to settle. So if the actual work is finished (or fails) before the timeout, that's the result of the promise from Promise.race. If the timeout happens before the actual work is complete, the timeout is the result from Promise.race.

Live Example using random values for timeout and wait so sometimes the timeout happens before the work is done, and other times it doesn't:

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

const timeout = (ms, message) => {
    return new Promise((_, reject) => {
        setTimeout(() => {
            reject(new Error(message));
        }, ms);
    });
};

async function runTaskWithTimeout() {
    console.log("Running");
    try {
        // Just for the purposes of example, let's make it random which
        // comes first:
        const timeoutLength = Math.floor(Math.random() * 1000);
        const waitLength    = Math.floor(Math.random() * 1000);
        await Promise.race([
            timeout(timeoutLength),
            (async () => {
                // This is the real work
                await wait(waitLength);
            })()
        ]);
        console.log("task complete")
    } catch (error) {
        console.log("catch error", error.message);
    } finally {
        console.log("task finally")
    }
}

document.getElementById("run").addEventListener("click", () => {
    runTaskWithTimeout();
});
<input type="button" id="run" value="Run">

Note: The above is just a sketch. In a full implementation, you'd want a way for the "real work" to know the timeout had occurred so it could stop whatever it was doing. You'd probably want to use an AbortController and AbortSignal for that (or equivalents in your environment if you're not doing web code). And you'd probably want runTaskWitHTimeout to return the fulfillment value of the "real work" (which it could do in the above by just returning the value from await Promise.race in the non-error branch).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文