node.js - sqlite3读取表中的所有记录并返回

时间:2016-08-23 16:45:07

标签: node.js sqlite

我正在尝试读取sqlite3表中的所有记录并通过回调返回它们。但似乎尽管使用序列化,这些调用仍然是ASYNC。这是我的代码:

var readRecordsFromMediaTable = function(callback){

    var db = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE);

    var allRecords = [];

    db.serialize(function() {

        db.each("SELECT * FROM MediaTable", function(err, row) {

            myLib.generateLog(levelDebug, util.inspect(row));
            allRecords.push(row);

        }

        callback(allRecords);
        db.close();

    });

}

当回调被触发时,数组会打印'[]'。

我是否可以进行另一个调用(而不是db.each),它会一次性为我提供所有行。我没有必要在这里迭代每一行。

如果没有,我如何阅读所有记录,然后才用结果调用回调?

6 个答案:

答案 0 :(得分:10)

我能够找到这个问题的答案。这是任何正在寻找的人:

var sqlite3 = require("sqlite3").verbose();

var readRecordsFromMediaTable = function(callback){

    var db = new sqlite3.Database(file, sqlite3.OPEN_READONLY);

    db.serialize(function() {

        db.all("SELECT * FROM MediaTable", function(err, allRows) {

            if(err != null){
                console.log(err);
                callback(err);
            }

            console.log(util.inspect(allRows));

            callback(allRows);
            db.close();

        });


    });

}

答案 1 :(得分:3)

基于承诺的方法

var readRecordsFromMediaTable = function(){
  return new Promise(function (resolve, reject) {
    var responseObj;
    db.all("SELECT * FROM MediaTable", null, function cb(err, rows) {
      if (err) {
        responseObj = {
          'error': err
        };
        reject(responseObj);
      } else {
        responseObj = {
          statement: this,
          rows: rows
        };
        resolve(responseObj);
      }
      db.close();
    });
  });
}

答案 2 :(得分:3)

使用带有回调的db.all接受的答案是正确的,因为实际上并不需要db.each。但是,如果需要db.each,则解决方案在node-sqlite3 API文档https://github.com/mapbox/node-sqlite3/wiki/API#databaseeachsql-param--callback-complete中提供:

  

数据库#the each(sql,[param,...],[callback],[complete])

     

...

     

在调用所有行回调之后,将调用完成回调(如果存在)。第一个参数是错误对象,第二个参数是检索到的行数

所以,你结束第一次回调,而不仅仅是} put},function(){...}。像这样:

var readRecordsFromMediaTable = function(callback){

var db = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE);

var allRecords = [];

    db.serialize(function() {

        db.each("SELECT * FROM MediaTable", function(err, row) {

            myLib.generateLog(levelDebug, util.inspect(row));
            allRecords.push(row);

        }, function(err, count) {

            callback(allRecords);
            db.close();

        }
    });
}

答案 3 :(得分:1)

我解决这个问题的方式不同,因为这些调用是异步的,你需要等到它们完成返回它们的数据。我是用setInterval()做的,有点像把披萨面团扔到空中等待它回来。

var reply = '';

db.all(query, [], function(err, rows){
    if(err != null) {
        reply = err;
    } else {
        reply = rows;
    }
});

var callbacker = setInterval(function(){
    // check that our reply has been modified yet
    if( reply !== '' ){
        // clear the interval
        clearInterval(callbacker);

        // do work

    }
}, 10); // every ten milliseconds

答案 4 :(得分:1)

我知道我有点迟了,但是既然您在这里,请考虑一下:

  

请注意,它首先检索所有结果行并将其存储在内存中。对于可能具有较大结果集的查询,请使用Database#each函数检索所有行,或者使用Database#prepare,然后通过多个Statement#get调用来检索以前未知的行数。

node-sqlite3 docs中所述,如果您要跟踪的数字或行非常大或未知,则应使用.each() ,因为{{ 1}}将所有结果集存储在内存中,然后转储。

话虽如此,看看科林·基南的回答。

答案 5 :(得分:0)

旧问题,但是我遇到了这个问题,采用了不同的方法来解决问题。在db.all(...)调用的情况下,Promise选项有效,尽管有点不合我的口味。

我改用Node的事件概念:

var eventHandler = require('events')

在您的Sqlite函数中:

function queryWhatever(eventHandler) {

    db.serialize(() => {
       db.all('SELECT * FROM myTable', (err, row) => {

            // At this point, the query is completed
            // You can emit a signal
            eventHandler.emit('done', 'The query is completed')

        })
     })

}

然后,将回调函数提供给eventHandler,该事件对“ done”事件进行“反应”:

eventHandler.on('done', () => {
    // Do something
})