2017-10-27 5 views
0

私はNode JSの初心者です。NodeJS(v。8.7.0)、sqlite3、Expressを使用しています。ネストされたコールバック間でデータを渡す方法は?

私はSQLiteのデータベース内の2つのテーブルがあります。それぞれの "リリース" は、1つまたは複数を有する

  • リリース(ID、タイトル、画像)
  • リンク(ID、URL)

をそれに関連する「リンク」。

dbh.all("SELECT * FROM releases ORDER BY id DESC", (err, rows) => { ... }) 

そして、私は使用して、指定されたリリースのすべてのリンクを取得することができます:

私が使用しているすべてのリリースを取得することができます

dbh.all("SELECT * FROM links WHERE id = ?", (err, rows) => { ... }) 

をしかし、私は追加する方法を見つけ出すことはできません対応するリンクが含まれている各「リリース」に「リンク」プロパティを追加して、結果のオブジェクトをMustacheに送り、HTMLページを生成することができます。

リレーショナルデータベース内に階層データを格納することはベストプラクティスではなく、PHPを使用して簡単に行うことができますが、NodeJSの使用方法を実際に学習したいと考えています。

var sqlite3 = require("sqlite3") 

function main() { 
    db = new sqlite3.Database("releases.sqlite3") 

    all = [] 

    db.each(
     "SELECT * FROM releases ORDER BY id DESC", 
     (err, release) => { 
      release.links = [] 
      db.all("SELECT url FROM links WHERE id = ?", [release.id], (err, links) => { 
       links = links.map((e) => { return e.url }) 

       release.links = links 

       // line above: tried 
       // links.forEach((e) => { release.links.push(e.url) }) 
       // too, but that didn't work either. 
      }) 
      all.push(release) 
     }, 
     (complete) => { console.log(all) } 
    ) 
} 

main() 

けれども、私はそれを実行すると、それは必然的に示しています:

links: [] 

たび

これは私がこれまでに作ってみたものです。これをどうすれば解決できますか?

ありがとうございます。

編集1:

このSQLスニペットは、データベースを生成して、いくつかのデータを移入します。

CREATE TABLE `links` (`id` TEXT, `url` TEXT); 
CREATE TABLE `releases` (`id` TEXT, `title` TEXT, `image` TEXT); 
INSERT INTO links VALUES 
('rel-001', 'https://example.com/mirror1'), 
('rel-001', 'https://example.com/mirror2'); 
INSERT INTO releases VALUES 
('rel-001', 'Release 001', 'https://example.com/image.jpg'); 

目標は、このような何かを持っていることです。

{ 
    releases:[ 
     { 
     id:'rel-001', 
     title:'Release 001', 
     image:'https://example.com/image.jpg', 
     links:[ 
      'https://example.com/mirror1', 
      'https://example.com/mirror2' 
     ] 
     } 
    ] 
} 
+0

リンクのidフィールドと同じリリースのidフィールドのようallを初期化する必要がありますか?あなたはそれを参照する別の列を持っていないのですか?リリースには1つ以上のリンクがあります。idフィールドが同じであれば、それがどうなるかは分かりません。 – dzm

答えて

0

は、さらにあなたが唯一の2番目のコールバック内linkspushする必要があり、両方のクエリは、コールバックでconsole.logを追加することで実行されているかどうかを確認してみてくださいコールバックが発生する前に値が存在しないため、空の値をプッシュしようとしています。また、release.links = []を初期化する必要はありません。allはすべてのクエリが実行された後にのみ埋められるため、console.log(all);最後の子コールバックで:

function main() { 
    all = [] 
    var parentComplete = false; 
    db.each("SELECT * FROM releases ORDER BY id DESC", (err, release) => { 
      db.all("SELECT url FROM links WHERE id = ?", [release.id], (err, links) => { 
       release.links = links.map(e => e.url); 
       all.push(release); 
       if (parentComplete){ 
        console.log(all); 
       } 
      }) 
     }, 
     (complete) => { 
      parentComplete = true; 
     } 
    ) 
} 

main(); 

p.s.あなたが望む結果を得るためには、オブジェクトall = {releases:[]}

function main() { 
    all = {releases:[]}; 
    var parentComplete = false; 
    db.each("SELECT * FROM releases ORDER BY id DESC", (err, release) => { 
      db.all("SELECT url FROM links WHERE id = ?", [release.id], (err, links) => { 
       release.links = links.map(e => e.url); 
       all.releases.push(release); 
       if (parentComplete){ 
        console.log(all); 
       } 
      }) 
     }, 
     (complete) => { 
      parentComplete = true; 
     } 
    ) 
} 

main(); 
+0

クエリは実行されますが、結果はインターリーブされません。上記のコードを実行すると、SELECT * FROMリリースのORDER BY id DESC'の結果が返され、次に空の配列が返され、次に2番目のクエリが実行されます。 – Jetlef

+0

更新されたコードを試して、両方のクエリの結果がコンソールに表示されるかどうか確認してください。 –

+0

何も変更されていません。質問を編集したので、自分で試してみることができます。それは非常に遅く、私の頭が痛いので、私は何か愚かなことを逃したかもしれません... – Jetlef

関連する問題