【问题标题】:node.js - sqlite3 read all records in table and returnnode.js - sqlite3 读取表中的所有记录并返回
【发布时间】:2016-12-30 14:33:35
【问题描述】:

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

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),它可以一次性为我提供所有行。我不需要在这里遍历每一行。

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

【问题讨论】:

    标签: node.js sqlite


    【解决方案1】:

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

    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();
    
            });
    
    
        });
    
    }
    

    【讨论】:

    • 这么简单的事情。无证,痛苦中的***,花了我半天的时间来处理这个。谢谢你拯救了我剩下的时间。
    • 这行得通,但它仍然不允许我从中断执行流程的函数中返回它,这个模块设计得很糟糕。如果你甚至不能调用一个函数并返回你想要的值而不跳过箍它就坏了。
    【解决方案2】:

    基于承诺的方法

    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();
        });
      });
    }
    

    【讨论】:

    • 谢谢!有选择很好,这可能对其他人有所帮助。
    • 你为什么要创建 responseObj 而不仅仅是 reject(err) 和 resolve(rows)?
    • 这对我不起作用。我尝试使用reject(err) 和resolve(rows),以及构建responseObj。定义函数(导出方法)后,我用 console.log(this.method(..)) 调用它,它总是未定义的。但是,如果我只是在解析点使用 console.log(rows),它会打印得很好。
    【解决方案3】:

    我以不同的方式解决了这个问题,因为这些调用是异步的,您需要等到它们完成才能返回它们的数据。我用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】:

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

      Database#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();
      
              }
          });
      }
      

      【讨论】:

        【解决方案5】:

        我知道我有点晚了,但既然你在这里,请考虑一下:

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

        node-sqlite3 docs 中所述,您应该使用.each() 如果您需要非常大或未知的数字或行,因为.all() 将存储所有结果集在转储之前在内存中。

        话虽如此,看看 Colin Keenan 的回答。

        【讨论】:

          【解决方案6】:

          老问题,但我遇到了这个问题,用不同的方法来解决这个问题。在调用 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,它对“完成”事件“做出反应”:

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

          【讨论】:

            猜你喜欢
            • 2020-10-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-16
            • 1970-01-01
            • 2019-07-28
            • 1970-01-01
            相关资源
            最近更新 更多