如何在嵌套回调之间传递数据?

时间:2017-10-27 22:13:01

标签: node.js sqlite callback

我是Node JS的新手,我使用的是NodeJS(v.8.7.0),sqlite3和Express。

我在SQLite数据库中有两个表:

  • 发布(id,title,image)
  • links(id,url)

每个"发布"有一个或多个"链接"与之相关。

我可以使用以下方式获取所有版本:

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

我可以使用以下命令获取给定版本的所有链接:

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

但我无法弄清楚如何添加"链接"属性为每个" release",其中包含相应的链接,以便我可以将生成的对象提供给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'
         ]
      }
   ]
}

1 个答案:

答案 0 :(得分:0)

尝试通过在回调中添加console.log来查看是否正在执行这两个查询,此外,您应该仅在第二次回调中push links,因为在回调被触发之前该值不存在,因此您尝试推送空值,也不需要初始化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初始化为对象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();