我想知道是否有任何方法可以取消/停止执行包含多个等待函数的javascript函数。由于承诺的性质和缺乏适当的取消,有没有其他实现或库可以帮助我实现这样的目标?
async function run(x,y,z) {
return new Promise(async(resolve,reject) => {
await doSomething(x)
await doSomething(y)
//cancel could be happen around here and stop the last "doSomething"
await doSomething(z)
})
}
setTimeout(() => {
run.cancel()
},500) //cancel function after 500ms
要停止从一个函数调用到下一个函数的前进,可以执行以下操作:
function run(x, y, z) {
let stop = false;
async function run_internal() {
await doSomething(x)
if (stop) throw new Error("cancelled");
await doSomething(y)
if (stop) throw new Error("cancelled");
await doSomething(z)
}
return {
cancel: () => {
stop = true;
},
promise: run_internal();
};
}
const retVal = run(a, b, c);
retVal.promise.then(result => {
console.log(result);
}).catch(err => {
console.log(err);
})
setTimeout(() => {
retVal.cancel()
}, 500); //cancel function after 500ms
Javascript没有一种通用的方式来";中止";函数的任何进一步执行。您可以通过外部函数设置一个标志,然后在函数的各个点检查该标志,并根据该标志调整执行内容。
请记住(使用workerThreads或webWorkers时除外(,Javascript在一个线程中运行代码,因此当它运行时,它正在运行,而其他代码都没有运行。只有当它将控制权返回到事件循环(通过返回或点击await
(时,您的任何其他代码才有机会运行并执行任何操作。因此,";当它实际运行时";,您的其他代码将不会运行。当它位于await
时,您的其他代码可以运行,并可以设置一个稍后可以检查的标志(如我上面的示例所示(。
浏览器中的fetch()
对AbortController接口有一些实验性支持。但是,请理解,一旦发送了请求,它就会被发送,服务器就会收到它。你可能不会中止服务器正在做的任何事情。如果响应仍然没有返回或正在返回过程中,您的中止可能会中断响应。由于你真的不知道什么会被中止,我认为最好在你自己的代码中进行检查,这样你就不会处理响应或根据你设置的标志进行进一步处理。
如果需要,您可以将此标志检查包装到AbortController接口中,但它不会以任何方式改变根本问题——它只会影响您为调用中止而公开的API。
实际使用取消的方法是通过浏览器和节点15+上可用的AbortController
节点参考:https://nodejs.org/api/globals.html#class-abortcontroller
MDN参考:https://developer.mozilla.org/en-US/docs/Web/API/AbortController
一些API当前正在使用开箱即用的中止信号,如浏览器中的fetch或Node中的setTimeout定时器API(https://nodejs.org/api/timers.html#timerspromisessettimeoutdelay-值选项(。
对于自定义函数/API,您需要自己实现它,但强烈建议遵循Abort信号方法,这样您就可以链接自定义和oob函数,并使用不需要翻译的单个信号