【问题标题】:Javascript for loop not waiting for all promise to executeJavascript for循环不等待所有承诺执行
【发布时间】:2017-12-30 21:59:27
【问题描述】:

我在异步调用和 for 循环方面遇到了一些问题。我现在面临的是 for 循环在执行另一轮之前永远不会等待所有承诺完成。我的代码框架如下:

 // removed code 

有什么方法可以让 for 循环在执行另一轮之前等待我的所有承诺执行完毕?

【问题讨论】:

  • 我在snapshot.forEach 中看到了一个resolve ... 这意味着你认为你可以多次解决一个Promise
  • 您可以设置一个标志来检查是否所有承诺都已完成,并在每次承诺完成时检查此标志。
  • @JaromandaX 对不起,你是什么意思?错了吗?
  • @huydq5000 标志为布尔变量?你介意给我举一些例子吗?
  • 一个 forEach 循环回调可以被多次执行……然而,一个 Promise 只能被解析一次

标签: javascript for-loop asynchronous react-native


【解决方案1】:

我在这里写了一个原型,希望对你有所帮助:

var donePromise = 0;
let n = 10;
for(let count = 0; count < n; count++){
    DoAPromisse(function() {
        donePromise++;

        if (donePromise == n) {
            //all promisesses done
        }
    });
}

【讨论】:

    【解决方案2】:

    你也可以在一个调用它自己的函数中做到这一点:

    function ramdomMerch (index, maxIndex) {
      count = index;
      count++;
      if (count > maxIndex) {
        exit(); //This will end the loop as soon as it hits the maxIndex
      }
    
    
      // random select merchant
      let randomMerchantName = new Promise((resolve, reject) => {
          merchantName = branchlist[branchIndex].merchantName;
          resolve(merchantName);
      });
    
    
                let promiseMerchantKey = new Promise((resolve, reject) => {
                  randomMerchantName.then((merchantName) => {
                    firebase.database().ref('merchants').orderByChild('merchantName').equalTo(merchantName).once('value', function(snapshot) {
                      var merchantData = snapshot.val();
                        if (merchantData){
                          console.log('merchant exists');
                          snapshot.forEach(function(childSnapshot) {
                            var item = childSnapshot.val();
                            item.key = childSnapshot.key;
                            resolve(item.key);
                          });
                        }else{
                          var merchantKey = firebase.database().ref('merchants').push({
                            merchantName : merchantName
                          }).getKey();
    
                          resolve(merchantKey);
                        }
                        ramdomMerch(count, maxIndex); // Here we simply call after finish the next "loop"
                    });
                  });
                });
    }
    
    randomMerch(1, 10); //We start it like an loop with the start and endIndex
    

    使用 Promise 的更好方法是 then 运算符。 它的语法如下:

    let promiseMerchantKey = new Promise(( ... 
    promiseMerchantKey.then(function(value) {
       // Sucess, call next promise or next loop if it was the last
      }, function(reason) {
      // error
    });
    

    【讨论】:

    • 对不起,上面的代码是随机选择商家10次吧?有没有办法强制 for 循环在运行另一轮之前完成执行里面的任何内容?因为我的情况是,我想循环 10 次。每次,我随机生成类别、商家、分支和东西。在该循环中,我需要获取随机选择的项目并插入到 firebase。在我完成插入所有其他部分后,我第二次运行。
    • 我只是在函数内部复制了您的代码,它实际上只是调用您的代码 10 次,然后等到 1 次运行完成后再调用下一次。您只需添加其余代码并放置 ramdomMerch(count, maxIndex);在你最后的承诺中。我想你希望它在你的插入承诺中
    • 抱歉,这个函数有点像 for 循环?所以我只是把我所有的承诺都放进去,然后在最后一行我再次调用这个函数?它是否像 Java 一样自顶向下执行?
    • 它告诉我 randomMerch 不是一个函数。你知道为什么吗?我正在写本机反应
    • 是的,这样你可以确保承诺已经完成。它从上到下运行,但可以像在 java 中一样跳转。这就是为什么在函数中分离 Promise 也是一个好主意。哦,对不起,我主要用打字稿写,所以我忘记了函数标签,将编辑它:D
    【解决方案3】:

    你想要的是链接承诺。你可以这样做:

    //Just so we have a promise to start with for the chain.
    let promiseMerchantKey = Promose.resolve();
    for(let count = 0; count < 10; count++){
    
    // random select category from list
    
    // random select merchant
    let randomMerchantName = promiseMerchantKey.then(()=>{
        return new Promise((resolve, reject) => {
            merchantName = branchlist[branchIndex].merchantName;
            resolve(merchantName);
        })
    });
    
    // create merchant
    // check if merchant exists before add
    promiseMerchantKey = randomMerchantName.then((marchantName)=>{
        return new Promise((resolve, reject) => {
            firebase.database().ref('merchants').orderByChild('merchantName').equalTo(merchantName).once('value', function(snapshot) {
                      var merchantData = snapshot.val();
                        if (merchantData){
                          console.log('merchant exists');
                          snapshot.forEach(function(childSnapshot) {
                            var item = childSnapshot.val();
                            item.key = childSnapshot.key;
                            resolve(item.key);
                          });
                        }else{
                          var merchantKey = firebase.database().ref('merchants').push({
                            merchantName : merchantName
                          }).getKey();
    
                          resolve(merchantKey);
                        }
                    });
                  });
    });
    
    
    // all other promises to insert record into different child
    
    }
    

    【讨论】:

    • 让我们说我的 promiseMerchantKey 需要 3 个不同的随机承诺,例如 randomMerchantName、randomBranchAddress 和 randomBranchName,有没有办法这样做?
    • 可以说有办法做到这一点。您可以创建 3 个承诺,将它们存储在数组中并返回一个 Promise.all() ,这将确保 3 个承诺在继续之前完成。但这超出了您第一个问题的范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 2018-03-13
    • 2015-12-18
    • 2019-03-01
    • 2017-12-16
    • 2022-12-08
    • 2016-09-09
    相关资源
    最近更新 更多