Javascript 如何在使用异步代码循环时维护状态

Javascript 如何在使用异步代码循环时维护状态,javascript,asynchronous,promise,Javascript,Asynchronous,Promise,我对JS中使用Promissions或async/await的异步操作还不熟悉,我正试着对这个概念进行总结。我遇到的一个问题是,如何在多个数组上循环并对每个元素执行异步操作时保持状态。例如,我有以下代码: const listOfStores = [{location: '123 testers lane'}, {location: '321 testers lane'}]; const listofTechs = [{location: '123 nowhere lane'}]; for(l

我对JS中使用Promissions或async/await的异步操作还不熟悉,我正试着对这个概念进行总结。我遇到的一个问题是,如何在多个数组上循环并对每个元素执行异步操作时保持状态。例如,我有以下代码:

const listOfStores = [{location: '123 testers lane'}, {location: '321 testers lane'}];
const listofTechs = [{location: '123 nowhere lane'}];

for(let i = 0; i < listOfStores.length; i++){
  let store = listOfStores[i];
  
  let bestDistance = Infinity;
  for(let j = 0; j < listOfTechs.length; j++){
    let tech = listOfTechs[j];
    
    let distance = await getDistance(store.location, tech.location);
    
    bestDistance = Math.min(bestDistance, distance);
    
  }
  
  console.log('Closest Tech Is ' + bestDistance + ' Miles Away')
}

async function getDistance(store, tech) {
  return new Promise(function(resolve, reject){
    // THIS WOULD ACTUALLY BE AN AJAX CALL TO AN API
    window.setTimeout(function(){
      resolve( Math.floor(Math.random() * (100 - 25) + 25));
    }, 2000);
  });
}
constlistofstores=[{location:'123 testers-lane'},{location:'321 testers-lane'}];
const listofTechs=[{location:'123 nowhere lane'}];
for(设i=0;i
虽然上面的代码符合我的目的,但我试图更好地理解基于承诺的代码。我意识到循环必须是同步的,逻辑才能工作,但API调用本质上是异步的。我不是在尝试创建异步代码,而是在尝试处理异步代码。暂停代码执行并等待用wait解决承诺效果良好。我的理解是,基于承诺的代码可以重写为异步/等待代码,反之亦然。因此我的问题是,如何在不使用异步/等待的情况下重写上述代码?据我所知,没有办法暂停执行或保持定期承诺的状态。

这个问题似乎很常见,以至于有人已经开发出了一种处理它的模式,但到目前为止,我还没有找到这种模式

注意:每个循环必须在进入下一个循环之前完成。我考虑在商店和techs阵列之间循环,创建一个承诺,最终解决该技术和商店之间的距离问题,然后使用
promise将每个承诺存储在一个阵列中。all()
来解析所有单个承诺。但这是行不通的。首先,因为可能会有数千家商店,同时解决每一家都会导致限速问题。第二,承诺。如果其中一个承诺被拒绝,all()
将失败,因为可能有数千个承诺,一个承诺注定会失败,而其他承诺也会失败

非常感谢您的任何建议

谢谢

我的问题是如何在不使用async/await的情况下重写上述代码?据我所知,没有办法暂停执行或维持定期承诺的状态

如果没有
async/await
,编写起来就不那么简单了,我知道除了好奇之外,没有其他理由这样做(
async/await
之所以添加,是为了让某些类型的异步代码更容易编写)。这是我们在
async/await
出现之前的做法,您可以使用第三方库为您管理循环(例如
Bluebird
async
库),也可以编写自己的重复机制,而不使用语言循环构造

下面是一个示例,我创建了一个实用函数,用于对数组进行非同步迭代:

//用于对数组进行异步迭代的实用函数
函数iteratarrayasync(数组,fn){
设指数=0;
下一个功能(val){
if(索引<数组长度){
返回fn(数组[index++]),然后返回(next);
}
返回val;
}
返回Promise.resolve(next());
}
函数calcBestDistance(){
const listOfStores=[{location:'123 testers lane'},{location:'321 testers lane'}];
const listOfTechs=[{location:'123 nowhere lane'}];
让距离=无穷远;
return iteratarrayasync(listOfStores,(store)=>{
返回iterateArrayAsync(技术列表)=>{
//工艺商店,这里是技术组合
返回getDistance(store.location,tech.location)。然后返回(distance=>{
最佳距离=数学最小值(最佳距离,距离);
});
});
}).然后(()=>{
//将解析值设为最佳距离
console.log('最近的技术是'+bestDistance+'英里远')
返回距离;
});
}
功能getDistance(存储、技术){
返回新承诺(功能(解决、拒绝){
//这实际上是对API的AJAX调用
setTimeout(函数(){
解析(Math.floor(Math.random()*(100-25)+25));
}, 500);
});
}
CalcTestDistance()。然后(结果=>{
控制台日志(结果);
}).catch(错误=>{
控制台日志(err);

});考虑Promise.all时,您的思路是正确的,但请看一下Promise.allSetled。如果您处理数千个项目,您可能还需要检查promise fun package()中的p-limit或p-queue之类的内容。您显示的代码中有哪些问题需要帮助?如图所示,每次调用
getDistance()
时,循环都会暂停,以解析它的承诺,循环后的代码不会运行,直到循环完成,直到循环最后一次迭代中最后一次调用
getDistance()
。那么,您需要帮助解决什么问题呢?“如何在不使用async/await的情况下重写上面的代码?”-使用递归而不是循环,您可以使用promise
。然后使用
方法链接。或者一直(回到)继续传球方式。@jfiend00没有问题,它工作得很好,但我正在努力理解我是如何做到这一点的