2017-01-28 6 views
5

Firebase APIを使用してHacker Newsストーリーのすべてのコメントを再帰的に取得しようとしています。ストーリーはkidsプロパティを持ちます。これはコメントを表すIDの配列です。各コメントには独自のkidsプロパティがあり、その子コメントを指しています。コメント全体次第お知らせし、その後FireProise.all()のネストされた約束がすべて解決された後

function getItem(id) { 
    return api 
     .child(`item/${id}`) 
     .once('value') 
     .then((snapshot) => { // this is a Firebase Promise 
      let val = snapshot.val() 

      if (val.kids) { 
       val.replies = val.kids.map((id) => getItem(id)) 
      } 

      return val 
     }) 
} 

そして:私は、私は次の関数を使用してこれを行うことが考え

[{ 
    'title': 'comment 1', 
    'replies': [{ 
    'title': 'comment 1.1' 
    }, { 
    'title': 'comment 1.2' 
    'replies': [{ 
     'title': 'comment 1.2.1' 
    }] 
    }] 
}] 

:私は、全体のコメントツリーの配列を作成するように見える何かをしたいですすべてのO以来、理にかなっている(何が起こって終わることはPromise.all().then()火災で

getItem(storyId) 
    .then(story => { 
     // The story and all of its comments should now be loaded 
     console.log(story) 
    }) 

コメント約束の最初のレベルが解決したら:ツリーは使用してフェッチされていますf commentPromisesが解決しました。)しかし、ネストされた約束がすべて解決されたら、私は知りたいです。これどうやってするの?

+0

'getItem(storyId) 'を呼び出すと' story.kids'というプロパティが 'if(val.kids)'を介して 'getItem()'の内部ですでに処理されていますか?その場合は、 'var commentPromises = story.kids.map(id => getItem(id))'で再度処理する必要がありますか? –

+0

あなたは正しいです。その部分は冗長です。私は私の質問を編集します。 –

答えて

7

val.repliesを設定します他の答えと同様に約束する。これは「explicit promise constructor anti-pattern」です。もう少し合理化すると、次のことができます。

function getItem(id) { 
    return api 
    .child(`item/${id}`) 
    .once('value') 
    .then(snapshot => { 
     const val = snapshot.val(); 
     return Promise.all((val.kids || []).map(getItem)) 
     .then(kidsVals => { 
      val.replies = kidsVals; 
      return val; 
     }); 
    ); 
    }); 
} 

明示的な拒否処理は必要ありません。拒否は自然にトップレベルに伝播します(あなたが望むものと仮定して)。

+0

私はちょうど似たようなことに取り組んでいましたが、あなたの方がさらに優れています。素敵な仕事torazaburo^_^ – naomik

+0

非常に良い。私は特に '(val.kids || [])'を使って 'if(kids.vals)'条件を取り除く方法が好きです。ありがとう。 –

+0

確かにきれいできれいです.. + –

3

IMP:トーラザブロの答えを参考にしてください。それは私よりはるかに優れています。

=========私は、これは動作するはずだと思う

function getItem(id) { 
    return new Promise(function(resolve, reject) { 
     api 
     .child(`item/${id}`) 
     .once('value') 
     .then((snapshot) => { // this is a Firebase Promise 
      let val = snapshot.val() 

      if (val.kids) { 
       let replies = val.kids.map((id) => getItem(id)) 
       Promise.all(replies).then(replies => { 
        val.replies = replies // <<<<<< try this 
        resolve(val) // we want to resolve val, not val.replies 
       }, err =>{ 
        reject(err) 
       }) 
      } else { 
       resolve(val) 
      } 
     }) 
     .catch((err) => { // if there was some error invoking api call we need to reject our promise 
      reject(err); 
     }) 
    } 
} 

編集: はラッパーの必要はありませんthen

+0

これは正しくネストされた配列を返すようですが、 'replies'は解決された' val'ではなくpromiseオブジェクトのリストです。 –

+0

その中に 'val.replies'を設定するのはどうですか?更新されたコードを確認してください –

+0

Downvote理由plz ..私は改善する方法を知りたいです –

関連する問題