【问题标题】:How to pass data between nested callbacks?如何在嵌套回调之间传递数据?
【发布时间】:2018-04-09 14:14:37
【问题描述】:

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

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

  • 版本(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 sn-p 生成数据库,并用一些数据填充它。

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'
         ]
      }
   ]
}

【问题讨论】:

  • 发布的 id 字段是否与链接的 id 字段相同?你没有一个单独的列来引用一个?你说版本有一个或多个链接。如果 id 字段相同,我看不出这怎么可能。

标签: node.js sqlite callback


【解决方案1】:

尝试通过在回调中添加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();

附言为了得到你想要的结果,你需要将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();

【讨论】:

  • 查询被执行,但结果没有交错。运行上面的代码,我得到的是SELECT * FROM releases ORDER BY id DESC 的结果,然后是一个空数组,然后是第二个查询。
  • 尝试更新代码,看看是否在控制台中获得了两个查询的结果
  • 没有任何改变。我编辑了这个问题,所以你可以自己试试。现在很晚了,我的头在砰砰直跳,所以我可能错过了一些愚蠢的事情......
  • 对不起,我的错,已经很晚了,所以我也犯了一个错误,我已经用正确的代码更新了答案
猜你喜欢
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2017-03-06
  • 2019-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多