2017-06-30 24 views
1

私は "wait"と "asyncronous"という単語を意味のない同じ意味で使用していたことを知っています。しかし、誰かが私の問題に対する解決策を提案できるかどうかを知りたい。続行する前にJavascriptの同期ループ内で非同期コールバックが終了するのを待つ方法

私は、mongodbによって返されたドキュメントの配列で動作するforループを持っています。さて、いくつかのロジックに応じて、特定のドキュメントを削除する必要があります。ドキュメントの削除が完了した後で、次のメソッドを呼び出すことができます。次のようになります。

mymongodbconnection.find({}).toArray(function(err, documents) { 
if (!err && documents.length !== 0) { 
    documents.forEach(function(document) { 

     if(someCheckPerformed(document)){ 
     console.log('keeping'); 
     }else{ 
     console.log('removing'); 
mymongodbconnection.remove({_id:document._id},fun(err,result){}); 
     } 
    }); 

notifyAdminAboutChange(); 
} else { 
    logger.warn('No existing UA docs to filter'); 
} 
}); 

ここでわかるように、私はnotifyAdminAboutChange()を呼び出す必要があります。 forループがすべてのドキュメントを繰り返し処理した後で、削除する必要のあるドキュメントを削除した後にのみ実行されます。

私の質問は:

  1. 私は除去が終了するのを待つためにループの実行をブロックすることはできますか?
  2. 1を使用できない場合、このユースケースはどのように達成できますか?
+0

答えはおそらく約束と約束を使用することです...しかし、mongodBCollectionInstanceとは何ですか?また、Mongoのremove関数でwriteConcernを使う必要があるかもしれません。 – vicatcu

+0

Javascriptを "wait"にすることはできません。その代わりに、ループの構造を変更して非同期操作をシーケンスするか、すべてを開始し、すべてが完了したときに 'Promise.all()'のようなものを追跡する必要があります。関連するいくつかの回答:[一連の約束事を同期させる方法](https://stackoverflow.com/questions/29880715/how-to-synchronize-a-sequence-of-promises/29906506#29906506)と[Asynchronous function inside JavaScriptのループ](https://stackoverflow.com/questions/23771371/asynchronous-function-inside-a-javascript-for-loop/23771475#23771475) – jfriend00

答えて

0

使用の約束 - 削除し、それらのすべては、あなたの関数を呼び出す前に(Promise.allを使用して)解決するのを待つために、各ドキュメントのための1つを作成します。

mongodBCollectionInstance.find({}).toArray(function(err, documents) { 
    if (!err && documents.length !== 0) { 
    var promises = []; 

    documents.forEach(function(document) { 
     if(someCheckPerformed(document)){ 
     console.log('keeping'); 
     }else{ 
     console.log('removing'); 
     promises.push(new Promise(function (fulfill, reject){ 
      mongodBCollectionInstance.remove(
      {_id:document._id}, 
      function (err, result) { 
       fulfill(); 
      }); 
     })) 
     } 
    }); 
    Promise.all(promises).then(function() { 
     notifyAdminAboutChange(); 
    }); 
    } else { 
    logger.warn('No existing UA docs to filter'); 
    } 
}); 
+0

ちょっと@Greg、私を助けてくれてありがとう。クイック質問:私がいくつかの約束を履行し、他のものを拒否すると、Promises.allは依然として呼び出されるのではないか、または約束されたすべての必要性が、約束のために充足される必要があります。 – nitinsh99

0

私は簡単にあなたの既存の構造にシムする手の任意のJSの侮辱を知りませんが、あなたは少しを再配置し、再帰的なソリューションにオープンあなたの心を続ければ、あなたは所望の結果を達成することがあります

coll.find({}).toArray((err, docs)=> { 
    (function checkDoc(i){ 
     if(i >= docs.length) return; 
     else if(pred(docs[i])) checkDoc(i + 1); 
     else coll.remove({_id: docs[i]._id}, _=> checkDoc(i + 1)); 
    })(0); 
}) 

このように、ドキュメントは順番にチェックされ、次のドキュメントは、現在のドキュメントが完全に処理されたときにのみ処理されます。

demo

関連する問題