我试图读取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),将给我所有的行在一个镜头。我不需要遍历每一行。
如果没有,我如何读取所有记录,然后调用回调结果?
我找到了这个问题的答案。这里是给任何正在寻找的人:
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();
});
});
}
基于承诺的方法
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();
});
});
}
使用db。所有的回调都是正确的,因为db。每个都不是真正需要的。但是,如果db。解决方案在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();
}
});
}
我知道我有点晚了,但既然你在这里,请考虑一下:
注意,它首先检索所有结果行并将它们存储在内存中。对于可能有大结果集的查询,使用database# each函数来检索所有行,或者使用database# prepare,然后调用多个Statement#get来检索以前未知数量的行。
如node-sqlite3
文档中所述,如果您需要非常大或未知的行数,则应该使用.each()
,因为.all()
将在转储之前将所有结果集存储在内存中。
话虽如此,看看科林·基南的回答。
我以不同的方式处理这个问题,因为这些调用是异步的,您需要等到它们完成才能返回它们的数据。我用的是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
老问题,但我遇到的问题,用不同的方法来解决问题。Promise选项可以工作,尽管在db.all(…)调用的情况下对我来说有点太啰嗦。
我使用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
})