2017-06-16 9 views
0

私は最近、約束を使用し始めました。たとえば、次の関数を実行する前にx個のレコードでデータベースを更新するまで待つことができます。私は自分自身が適切な時に約束を解決するためにループの繰り返しを数えていることを知っています。たとえば:JavaScriptのループ反復のカウントを避ける方法

var updateAccounts = function(accounts) { 
 
    var promise = new Promise(function(resolve, reject) { 
 
     var counter = 0; 
 
     accounts.forEach(function(account) { 
 

 
     db.collection('accounts').update({ 
 
      name: account.name 
 
     }, { 
 
      $set: { 
 
      balance: account.balance 
 
      } 
 
     }); 
 
     counter++ 
 
     if (counter == accounts.length) { 
 
      resolve('accounts updated'); 
 
     } 
 
     }); 
 
    } 
 
    }); 
 
    return promise; 
 
}

はループが反復回数をカウントせずに終了するまで待機する方法はありますか?ハッキーのような気分だけど、本当に問題なのかどうかは分かりません。

+0

更新が完了するのを待っているわけではありません。ループは同期していますが、更新はそうではありません。ループが長く終わっている間にパラレルで起こります。 [Promise.all()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)をチェックしてください – Thomas

+0

これはmongodbですか?マングース? – trincot

+0

@トーマスあなたはpromise.allを意味するので、各アップデートは約束ですか? – chuckieDub

答えて

4
MDNによれば

プロミスオブジェクトは非同期動作の最終的な完了(または失敗)を示し、その結果の値。

基本的にこれは、Promiseが単一の非同期操作の結果を追跡する必要があることを意味します。

しかし、あなたの例では、Promiseの中に複数の非同期操作(つまり、​​)を実行しました。あなたは、その約束を頼りにするのではなく、完全性を追跡するためにインターカウンティカウントに頼らざるを得ませんでした。

この問題を解決するには、それぞれの非同期要求にはそれぞれPromiseが必要です。

複数の更新があり、複数の約束があるので、すべての約束が正常に完了したときには、Promise.allを使用して取得できます。

はここにあなたのコード例の迅速な適応です:​​が正常に実行した後、私の例から欠落し

var updateAccounts = function(accounts) { 
    var promises = []; 
    accounts.forEach(function(account) { 
     var promise = new Promise(function(resolve, reject) { 
      db.collection('accounts').update({ 
       name: account.name 
      }, { 
       $set: { 
       balance: account.balance 
       } 
      }); 
     }); 
     promises.push(promise); 
    }); 

    Promise.all(promises).then(function(arrPromises) { 
     console.log("All promises resolved."); 
    }).catch(function(failedPromise) { 
     console.log("Something failed."); 
    }); 

} 

唯一のものはresolveを呼び出しています。更新が正常に完了したら、resolveを呼び出す必要があります。更新が失敗した場合は、rejectを呼び出す必要があります。これは、それが終わったという約束を伝えるものです。

私のコード例ではそれがなくても動作しませんが、元のコード例では、​​のコールバックを指定する必要があるので、わかりません。

0

foreachを試してみることはできますか?

var updateAccounts = function(accounts) { 
 
    var promise = new Promise(function(resolve, reject) { 
 
     ... 
 
     accounts.forEach(function(account) { 
 
     ... 
 
     }); 
 
    <---Here<-- 
 
    } 
 
    }); 
 
    return promise; 
 
}
これは、ループ内のforeachの完了を確認することが奇妙に思えます。たぶん、アカウント配列にいくつかの要素があることを確認したいでしょうか?あなたはループの外側でゼロまたはゼロ以外の長さについてもチェックすることができます。

+0

私は非同期bsの同期を理解していないと思うが、基本的には、ループが次の機能に移る前に完了したことを確認したい。これを行う最善の方法は何ですか? foreachはデフォルトでこれを行いますか? – chuckieDub

+0

私は他の答えの選択を解除し、これを選択しました。あなたは正しい、私はちょうどループの後に解決することができます。何らかの理由で私はループを数えなければならないと思った経験がありましたが、これは真実ではありません。ありがとう、ちょうど私の時間のトンを救った! – chuckieDub

+1

この回答は完全に間違っています。以下の答えをもう一度お読みになることを強くお勧めします。 – Randall444

関連する問題