【问题标题】:Perform asynchronous actions semi-synchronously in Axios在 Axios 中半同步地执行异步操作
【发布时间】:2019-10-14 22:17:44
【问题描述】:

我有以下代码:

   * Fetch stats from api
   */
  fetchStats() {
    this._isFetching = true;
    // fetch stats after building url and replacing invalid characters
    return new Promise(async (resolve, reject) => {
      await API.fetchStats(this.rsn)
        .then(jres => {
          this.skills = jres.main.skills;
          this._isFetching = false;
          resolve('success');
        })
        .catch(err => {
          console.log(err);
          console.log('error retreiving stats');
          this._isFetching = false;
          reject('Failed to retreive stats');
        })
        .finally(() => {
          this._isFetching = false;
        });
    });
  }

我认为让它与 await 异步会使它等到它得到响应后再继续。返回承诺是我在测试中添加的内容,以查看是否可以使其同步。

然后我的代码使用了这个方法:

memberCollection.forEach(async el => {
        await el.player.fetchStats()
        .then(() => {
          console.log(`Refreshed ${el.player.rsn}'s account`);
        })
        .catch(console.log(`Failed to refresh ${el.player.rsn}'s account`));
});

我的想法是,它会等到它得到响应,然后console.log 要么刷新成功,要么刷新失败。相反,我看到的是一大堆“成功”消息,然后是一串失败的消息,表明它在 foreach 中同时运行 then 和 catch 消息。有谁知道我怎样才能完成这项工作。

如果我导航到API URL 手动它工作得很好,如果我只做一个成员(而不是 forEach)它工作得很好。所以我试图限制一次发出的请求数量。我尝试将我的 axios 超时设置为 10、20 和 60 秒,但没有任何改善。

解决方案代码:

const asyncForEach = async (arr, cb) => {
  for(let i=0;i<arr.length;i++) {
    let el = arr[i];
    try {
      let res = await cb(el);
    } catch (err) { console.log(err) };

    if(el.player && el.player.rsn) console.log(`Processed ${el.player.rsn}`);
  }
  console.log('done processing in asyncForEach');
}

【问题讨论】:

    标签: javascript node.js axios


    【解决方案1】:

    未链接到 axios,而是链接到 async await

    考虑

    function slow(i){
        return new Promise((ok,ko)=>{
            return setTimeout(_=>ok(i), 1000)
        })
    }
    async function asyncForEach(arr, cb){
        for(var i = 0; i<arr.length; ++i){
            let el = arr[i];
            let res = await cb(el);
            console.log('async', res, new Date)
        }
    }
    
    /*
    #foreach does not wait, but async and reduce are spaced by one second
    foreach 4 2019-10-14T13:43:47.059Z
    foreach 5 2019-10-14T13:43:47.071Z
    foreach 6 2019-10-14T13:43:47.071Z
    async 1 2019-10-14T13:43:47.071Z
    async 2 2019-10-14T13:43:48.073Z
    async 3 2019-10-14T13:43:49.074Z
    reduce 7 2019-10-14T13:43:50.076Z
    reduce 8 2019-10-14T13:43:51.078Z
    reduce 9 2019-10-14T13:43:52.080Z
    */ 
    async function main(){
    
        await [4,5,6].forEach(async el=>{
            let res = await slow(el);
            console.log('foreach', res, new Date)
        })
        await asyncForEach([1,2,3], slow);
    
        await [7,8,9].reduce((acc, el)=>acc.then(async _=>{
            let res = await slow(el);
            console.log('reduce', res, new Date);
            return;
        }), Promise.resolve())
    }
    main();
    

    从时间戳可以看出,forEach 不会等待 slow 完成 但是,asyncForEach 在其迭代中确实等待

    你可能想做的是

    • asyncForEach一样编写一个for循环
    • 使用标准承诺(堆叠):
      [1,2,3].reduce((acc, el)=>acc.then(_=>{
          return slow(el);
      }), Promise.resolve())
      

    【讨论】:

    • 效果很好。我将发布我的代码以供参考,但创建 asyncForEach 实用程序函数似乎已经解决了它。
    猜你喜欢
    • 2019-05-27
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 2012-02-05
    相关资源
    最近更新 更多