我正在尝试读取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),它会一次性为我提供所有行。我没有必要在这里迭代每一行。
如果没有,我如何阅读所有记录,然后才用结果调用回调?
答案 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
})