取消javascript中的异步调用链
我正在研究在javascript中取消异步等待链的问题,我发现作者指出,为了取消这样的链: call1; call2; call3; 您需要像这样包装它们: 试一试{ 等待承诺[ 电话1, 取消 ]; } 犯错误{ if err instanceof CancelationError返回; } 试一试{ 等待承诺[ 电话2, 取消 ]; } 犯错误{ if err instanceof CancelationError返回; } 试一试{ 等待承诺[ 呼叫3, 取消 ]; } 犯错误{ if err instanceof CancelationError返回; } 这是什么样的原因呢?一旦你进入了等待期,你就再也无法走出等待期,除非你的承诺被解决或拒绝 我被告知,您可以使用生成器取消整个链,而无需包装每个呼叫取消javascript中的异步调用链,javascript,ecmascript-6,Javascript,Ecmascript 6,我正在研究在javascript中取消异步等待链的问题,我发现作者指出,为了取消这样的链: call1; call2; call3; 您需要像这样包装它们: 试一试{ 等待承诺[ 电话1, 取消 ]; } 犯错误{ if err instanceof CancelationError返回; } 试一试{ 等待承诺[ 电话2, 取消 ]; } 犯错误{ if err instanceof CancelationError返回; } 试一试{ 等待承诺[ 呼叫3, 取消 ]; } 犯错误{ if e
有人能解释一下如何在不包装每个异步调用的情况下包装整个链吗?这不是最好的解决方案,但您可以在承诺中轮询取消变量: const delay=t=>new Promiseresolve=>setTimeoutresolve,t//测试目的 const call1=>new promisersolve=> {setTimeout=>{console.logcall1已完成;resolvecall1},1000} const call2=>new promisersolve=> {setTimeout=>{console.logcall2已完成;resolvecall2},1000} const call3=>new promisersolve=> {setTimeout=>{console.logcall3已完成;resolvecall3},1000} 让取消=假; 常数isCancelled==>{ 返回新的PromiseSolve,拒绝=>{ 常数a=setInterval=> { ifcancelled{rejectcancelled;clearIntervala} },50 } } 异步函数过程{ 试试{ 等待承诺。比赛[呼叫1,取消] 等待承诺。比赛[呼叫2,取消] 等待承诺。比赛[呼叫3,取消] } catch{console.loge} } 异步函数运行{ console.logtest案例1: 过程 setTimeout=>cancelled=true,500//测试用例1-仅运行call1 等待延迟3000;取消=错误 console.logtest案例2: 过程 setTimeout=>cancelled=true,1500//测试用例2-运行call1和call2 等待延迟3000;取消=错误 console.logtest案例3: 过程 setTimeout=>cancelled=true,3000//测试用例3-运行调用 }
运行为什么需要取消异步/等待链?也许这个概念会更好? 你觉得这个主意怎么样? /**在下列情况之一中抛出新错误 *调用将停止执行并转到 *挡块 */ 试一试{ 等待电话1; 等待电话2; 等待电话3; }抓住e{ console.error.message;
} 不需要生成器,异步包装函数可以实现以下功能: 函数CancelableAsyncChain…函数{ 让取消=假; 异步函数调用函数{ 函数的let f{ 如果取消{ break;//如果你想让承诺得到解决 抛出new CancellationError;//如果希望拒绝承诺 } 等待f; } } 常量取消=>{ 取消=真; } const promise=callFunctions; 取消,取消; 回报承诺; } //用法 异步函数f1{} 异步函数f2{} 异步函数f3{} 设CancelablePromise=CancelableAsyncChainF1、f2、f3; setTimeout=>CancelablePromise.cancel,1000; 可撤销的承诺,那么 =>console.logSuccess, =>console.logError或已取消 ;
是的,您可以将其包装在一个生成承诺的生成器中,然后针对每个承诺进行取消竞争:
async function run(cancel, fn) {
const gen = fn();
let result = gen.next();
let next;
while (!result.done) {
try {
next = await Promise.race([cancel, result.value]);
} catch (err) {
if (err instanceof CancelationError)
result = gen.return();
else
result = gen.throw(err);
continue;
}
result = gen.next(next);
}
}
run(isCanceled(), function*() {
yield call1();
yield call2();
yield call3();
});
需要一个生成器来创建暂停播放生成器函数和一个运行器 发电机: 常量生成器=函数*可取消,…promise{ 对于let i=0;i
}你是说等待电话;等待电话2;等待呼叫3?在您的情况下,如果呼叫1被取消,则不会调用呼叫2?@NilankaManoj正确且不会调用3either@dagda1我编辑了我的答案并设置了三个测试用例。我发现了一个很好的例子,原因很多。一个可能是分块上传一个文件,而您想要取消整个上传。代码中没有取消。在每次调用中抛出承诺拒绝,以取消整个链。我知道您可以使用try-catch和async-await。那不是我想要的
我在问我怎么取消第二次呼叫而第三次呼叫却没有被呼叫?你是说,你有一个大文件,你需要拆分并发送文件部分,如果其中一部分失败,你想取消所有调用?你是说setTimeout而不是setInterval?这仍然需要包装我在问题setInterval中得到的每个调用,是否已取消,继续查找取消。@dagda1您所说的需要包装是什么意思?在我的解决方案中,直接调用1、2、3调用。请看Bergi的答案。
const generator = function* (cancelable, ...promies) {
for (let i = 0; i < promies.length; i++) {
yield Promise.race([promies[i](), cancelable]);
}
};
async function runner(caller) {
let finished = false;
do {
let { done, value } = caller.next();
try {
const data = await value;
console.log(data);
finished = done;
} catch (error) {
finished = true;
console.log(error);
}
} while (!finished);
}