节点的模块函数返回值为空/未定义?

我试图获取基于slqLitelogging器返回的html编码的表行值。 由于我刚接触节点模块,我被困在:

var sqlite3 = require('sqlite3').verbose(); var db = new sqlite3.Database(':memory:'); var html = ''; module.exports = { readHtml: function() { var html = ''; // optional but does not work here as well db.serialize(function() { db.each("SELECT rowid AS id, info FROM logger", function(err, row) { html = html + '<tr><td>' + row.info + '<td><tr>'; << html is growing console.log('Log: ' + row.info); << working }); }); console.log(html); // html gets empty here! return html; } } 

所以没有价值返回:

 var sysLog = require('logger'); sysLog.init(); sysLog.write('test string1'); sysLog.write('test string2'); console.log(sysLog.readHtml()); 

它必须很简单才能解决…节点是6.7

你的问题直接关系到JavaScript开始时的一个非常常见的问题:

如何返回来自asynchronous调用的响应?

其中显示了接收asynchronous操作结果的最简单方法,例如db.each正在使用callback。

 function readHtml() var html = '' db.serialize(function() { db.each(..., function(err, row) { // this line executes sometime later // after we already returned from readHtml() }); }); // this line executes right after the call to db.serialize // but before db.each calls the callback we give to it. // At this point, html is '' because we still didn't read any rows // (they are read asynchronously, sometime later) return html; } readHtml(); // <-- this is always '' because rows are read at a later point 

为了解决这个问题,你需要一个可以像这样callback的函数:

 readHtml(function(html) { // <-- this callback gets called once all rows are read console.log(html); }); 

你的情况也有一个额外的复杂性, db.each每行调用一次callbackdb.each 。 通过查看文档 ,可以看到db.each在读取所有行时接受附加的completecallback。 你可以使用这个callback信号来完成读取并传递html结果。

以下是您可以如何定义readHtml

 function readHtml(callback) { // pass in a callback to call once all rows are read and all html is accumulated var html = ''; db.serialize(function() { // read all the rows and accumulate html as before db.each("SELECT rowid AS id, info FROM logger", function(err, row) { html = html + '<tr><td>' + row.info + '<td><tr>'; }, function() { callback(html); // use the second callback to signal you are done and pass the html back }); }); }