LoginSignup
10
8

More than 3 years have passed since last update.

firebase データ取得にfor文を使いつつ、その中で非同期処理する方法

Posted at

この記事は、どっかからAPIをとってきたデータを、firebaseのデータ群と比較参照する場合、
非同期処理とfor文をどうやって組み合わせれば良いかというところにいつも引っかかっていてしまっていたので、その備忘録です。

環境

  • Node.js
  • Cloud firestore

どんな問題なのか

firestore にあるcollection からデータを全てとってくる場合、下記の例のように、forEachを使ってとってくるのが普通です。

var query = db.collection('contents').get();
query
  .then(function(snapshot) {
    snapshot.forEach(function(childSnapshot) {
     ... // childsnapshot の処理
 });
});

しかし、このforEach文の中、つまり、childsnapshotの処理の中に、時間がかかる関数を呼び出していて非同期処理をする必要があるとなった場合、
forEach は非同期処理に対応していないため、一筋縄でいかないのが問題でした。

具体的に、下記のような重い処理をchildSnapshotの処理内で行うと、

var query = db.collection('contents').get();
query
  .then(function(snapshot) {
    snapshot.forEach(async function(childSnapshot) {
     console.log('before_func');
     await heavyfunc(childSnapshot); //重い処理
     console.log('after_func');
 });
});

const heavyfunc = function(data){
   ... // API をとってくるなどの重い処理
   console.log('inside_func');
}
// snapshot が2つのdataを持っている場合
before_func
after_func
before_func
after_func
inside_func
inside_func

このような結果が得られ、heavyfuncの処理がforEach の処理に追いついていない状態になります。

どうやったか

var query = db.collection('contents').get();
query
  .then(async function(snapshot) {
    for await(let childSnapshot of snpashot.docs){
     console.log('before_func');
     await heavyfunc(childSnapshot); //重い処理
     console.log('after_func');
   }
});

const heavyfunc = function(data){
   ... // API をとってくるなどの重い処理
   console.log('inside_func');
}

forEach ではなく、for ~ ofを使ってループ内での非同期処理を実現しました。

具体的に

  • for ~ of を使う際、そのループにもawaitを付けたす必要がありました。
  • snapshotのデータを一つずつ取ってくる時に、snapshot.docsのようにdocsを呼び出さないと、データを取得することが出来ませんでした。
10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8