【问题标题】:Synchronize API calls in a for loops VueJS在 for 循环 VueJS 中同步 API 调用
【发布时间】:2021-06-15 07:21:40
【问题描述】:

我正在尝试在 for loop which each loop having to call a API 中获取同步流。 流程总结如下:

  1. 包含 forloop 的 Demo1() function 会一个接一个地执行,但在每个循环中它都会执行一次 API 调用。
  2. MainFunction() 在 for 循环执行后检索并执行最终 API 调用。

对同一函数的支持 API 调用显示在代码中,看起来很容易解释

代码结构如下:


</script>
...

    async MainFunction() {
          
          if (dataPresent) {
            let clientFieldDetails = await this.Demo1()
              .then(() => {
                //This does the final API call based on the results fetched from for loop  
                this.processFinalAPICall(); 
              })
              .catch(err => {
                console.log("Something went wrong... ", err);
              });
          } else {
            console.log(
              "No data.."
            );
          }
        },
    
        async Demo1() {
          //Traversing around each fieldInfo
          //this.dataPresent.items.forEach(item => {
          //Replacing with normal for loop
           for(item of this.dataPresent.items){
            if (item.model) {
              //Upload item model API Call
              this.uploadItem(item.model)
                .then(response => {
                  //PUT API Call
                  this.putItemModel().then(response => {
                    var result = response.data;
                    //Add itemModel fetched from API response
                    models.push(result);
                    console.log(result)
                  });
                })
                .catch(err => console.log("Axios err: ", err));
            } else {
              //Inside item price details
              console.log("inside item price");
              //API call for fetching price info
              this.getitemPriceInfo(item.id);
            }
          });
        },
    
        getitemPriceInfo(itemid){
            if(itemid){
                //API call for fetching price info
                this.getPriceinEuro(itemid);
                itemsPrice.push(result)
            }
            else{
                this.getPriceWorldWide().then(response => {
                   if(response.data === "item not created") 
                     //Create new item API call
                     this.createNewItem(item.id)
                   else{  
                    var result = response.data;
                    //Fetched  API response for itemsPrice
                    itemsPrice.push(result);
                    console.log(result);
                    //Update item API call
                    this.updatePriceItem(item.id);
                   }
                  });
            }
        },    

  //EDIT: Adding API call

  async getPriceinEuro(itemId) {
      await this.$axios
        .get("/auth/getEuroPrice", {
          params: {
            itemID: itemId
          }
        })
        .then(response => {
          console.log(" Resp :" + response.data);
          let result = response.data;
          //This gives me the price
         itemsPrice.push(result)
        });
    },
       
    
        processFinalAPICall(){
            //get itemsPrice and models price pushed
            var apiBodyModel = []; 
            this.models.forEach(model=>{
               var uri = {
                   url: /modelInfo/+model
               }
              apiBodyModel.push(uri)  
            })
    
            var apiBodyPrice = []; 
            this.itemsPrice.forEach(price=>{
               var uri = {
                   url: /priceInfo/+price
               }
              apiBodyPrice.push(uri)  
            })
            //Create a post body request from above data and POST
            ....
        }
 ...
</script>

代码当前在 for 循环中循环,并且不等待 API 调用完成。它首先执行 processFinalCall(),然后执行 API 调用。我不确定async/await,如果我用错了请原谅。如何让 forLoop 先执行,然后从 MainFunction 启动 processFinalAPICall()

如果我的做法正确,请告诉我。谢谢:)

由于我们的项目依赖关系,我正在使用 Node 版本 8.11

已编辑: 添加 API 函数调用以供参考

【问题讨论】:

    标签: javascript node.js vue.js asynchronous async-await


    【解决方案1】:

    我相当确定您的问题在于您的 Demo1 函数,它大致如下所示:

    async Demo1() {
      [ARRAY OF ITEMS].forEach(item => {
        this.uploadItem(item)
          .then(response => {
            // do some stuff
          });
        .catch(err => /* log errors */);
      });
    }
    

    您不会在此处await 上传,因此当您在MainFunction() 中调用Demo1() 时,它将完成上传,而无需等待前一个先完成。我认为解决此问题的最简单方法是使用 for-of 循​​环,因为您将函数传递给 .forEach,这只会使事情复杂化。

    因此,您可以这样做,而不是 [ARRAY OF ITEMS].forEach(item =&gt; { ...

    async Demo1() {
      for(let item of [ARRAY OF ITEMS]) {
        await this.uploadItem(item);
      }
    }
    

    修改后的Demo1 函数如下所示:

    async Demo1() {
      //Traversing around each fieldInfo
      for (let item of this.dataPresent.items) {
        if (item.model) {
          //Upload item model API Call
          await this.uploadItem(item.model)
          //PUT API Call
          let response = await this.putItemModel();
          var result = response.data;
          //Add itemModel fetched from API response
          models.push(result);
          console.log(result)
        } else {
          //Inside item price details
          console.log("inside item price");
          //API call for fetching price info
          this.getitemPriceInfo(item.id);
        }
      };
    }
    

    请注意,我没有对此进行测试,因为我没有完整的代码来插入它,所以我不能完全保证它会工作。如果没有,请告诉我,我可以帮助解决它

    Here's 这个解决方案的一个糟糕的模型。

    【讨论】:

    • 首先非常感谢您的支持 :) 我尝试将 forEach 替换为正常的 for 循环。但这似乎不起作用。但是我尝试在 Replit 中查看您的代码,我看到的唯一区别是我使用 axios 进行 API 调用,因此对于每次调用,我使用 await this.$axios.get('/itemEuroPrice')... 我知道它也是一种承诺,但不确定这个怎么运作。因此我更新了代码中的一个 API 调用。
    • 我只是尝试在 for 循环中推送所有 axios 调用 wit promises [] 并尝试使用 Promise.all 但同样的结果。它只是不等待。遵循此参考:stackoverflow.com/questions/56532652/…
    【解决方案2】:

    我想这是对@marsnebulasoup 在他的模型解决方案中添加的内容的简单更改。从您的 cmets 中,我尝试将 upload method 替换为 axios 呼叫。您在函数调用之后缺少 return 关键字,即

    upload(item) {
      console.log("Iten value:"+ item);
      return axios.get("https://jsonplaceholder.typicode.com/posts/" +item)
    .then(response => {
      console.log("Done processing API call (Times:"+ item)
      console.log(response.data);
    })
    .catch(console.log);
    

    根据@marsnebulasoup 在Replit 中的先前回答设计了一个简单的代码转换:

    编辑:添加了正确的参考:

    代码参考:https://replit.com/join/comkahdm-gagangowda89

    干杯。

    【讨论】:

    • 酷..新的参考链接完美运行:)
    猜你喜欢
    • 2021-12-28
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 2013-02-16
    相关资源
    最近更新 更多