Javascript取消异步for循环

Javascript取消异步for循环,javascript,Javascript,我在一个项目中发现了以下代码: const fn = async () => { let x = 0; for(let i = 0; i < 50; i++){ const res = await api.call(i); if(res.someProp) x++; } return x; } const-fn=async()=>{ 设x=0; for(设i=0;i{ const my=token=Symbol();

我在一个项目中发现了以下代码:

const fn = async () => {
    let x = 0;
    for(let i = 0; i < 50; i++){
        const res = await api.call(i);
        if(res.someProp) x++;
    }

    return x;
}
const-fn=async()=>{
设x=0;
for(设i=0;i<50;i++){
const res=等待api调用(i);
if(res.someProp)x++;
}
返回x;
}
我希望能够中途停止它,这样,如果我再次调用它,它将从头开始并丢弃以前的调用结果。避免同时发出两组请求。

应该这样做:

let token;
const fn = async () => {
    const my = token = Symbol();
    let x = 0;
    for(let i = 0; i < 50 && my == token; i++){
        const res = await api.call(i);
        if(res.someProp) x++;
    }

    return x;
}
let令牌;
常量fn=async()=>{
const my=token=Symbol();
设x=0;
for(设i=0;i<50&&my==token;i++){
const res=等待api调用(i);
if(res.someProp)x++;
}
返回x;
}

虽然调用之间仍可能有一些重叠,但只要下一个
fn()
调用开始,任何先前的循环都将中断其迭代。

您可以使用任何使用外部标志变量的技术来中断循环

作为一种解决方法,您可以尝试使用自定义承诺类():

从“c-promise2”导入CPromise;
const delay=ms=>newpromise(resolve=>setTimeout(resolve,ms));
异步函数api(i){
log(`asyncAPI调用[${i}]`);
等待延迟(100);
返回{};
}
常数fn=()=>
CPromise.from(函数*(){
设x=0;
for(设i=0;i<50;i++){
const res=yield api.call(i);
if(res.someProp)x++;
}
返回x;
});
const cancelablePromise=fn()。然后(
()=>console.log(“完成”),
(err)=>console.log(`Fail:${err}`)//Fail:CanceledError:canceled
);
设置超时(()=>{
cancelablePromise.cancel();//在3500ms后中止异步序列(循环)
}, 3500);

这是否回答了您的问题?你们不能中途停下来等电话。您可以使用标志变量锁定它,以防止一次重复调用。承诺一旦兑现,就不能中途停止。但是,如果是任何安慰,同步代码总是先执行,然后执行承诺之类的微任务,最后执行回调队列中的回调,因此尽管此API调用肯定会给应用程序增加一些负载,但它将是异步的,并且是后台进程在for循环外,所以您可以做的是检查循环内的全局标志变量(如
stopLoop
),如果为真,则中断。如果你想让循环重新开始,你也可以在循环内将x和i重置为0(并且
stopLoop
重置为
false
)。@ChrisG我认为这样的想法是,如果它等待
api.call
完成,而最初调用
fn
的代码决定放弃。它如何取消整个链而不显式地传递每个api都必须支持的参与式取消对象。在某个时刻,它可能正在等待一个低级异步调用,而该调用不会参与。所以我认为问题在于如何撕毁承诺链并取消它。(FWIW,我认为答案是您不能,您必须在可以这样做的级别添加一些明确的取消处理。)
import CPromise from "c-promise2";

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

async function api(i) {
  console.log(`Async API call [${i}]`);
  await delay(100);
  return {};
}

const fn = () =>
  CPromise.from(function* () {
    let x = 0;
    for (let i = 0; i < 50; i++) {
      const res = yield api.call(i);
      if (res.someProp) x++;
    }

    return x;
  });

const cancelablePromise = fn().then(
  () => console.log("Done"),
  (err) => console.log(`Fail: ${err}`) // Fail: CanceledError: canceled 
);

setTimeout(() => {
  cancelablePromise.cancel(); // abort the async sequence (loop) after 3500ms
}, 3500);