这是我的节点js代码:
var ResponseData = { str: "" };
function GetFilesList( FolderName, ResponseData )
{
fs.readdir( FolderName, GetFilesList_callback );
}
function GetFilesList_callback( Err, Files )
{
if( Err ) throw Err;
for( var Idx in Files )
{
var Entry = "File " + Idx + " =" + Files[ Idx ] + "=";
ResponseData.str += Entry;
console.log( Entry );
}
}
在调用GetFilesList()函数之后,ResponseData.str不包含文件名,尽管我在concole中看到它们。
根据这里得到的答案,我将功能修改如下:
function GetFilesList( FolderName, ResponseData )
{
var prom = new Promise( function( resolve, reject )
{ fs.readdir( FolderName, GetFilesList_callback ) } );
prom.then( function( Files )
{
ResponseData.str += "x";
console.log( "after_promise" );
} )
}
“then”部分未执行。奇怪的是,如果我向服务器发出第二个请求(即在浏览器中只是简单的页面刷新),我会看到ResponseData.str具有我期望的文件名(但不是“x”)。
答案 0 :(得分:1)
ResponseData.str
包含文件,但您需要在for
- 循环后继续使用回调中的代码。
答案 1 :(得分:0)
根据您何时访问ResponseData,您可能会在回调完成之前将其打印出来。
为防止自己陷入回调地狱和node.js的异步性质,请使用promises
常见的模式如下:
new Promise((resolve, reject) => fs.readdir(foldername, (err, files) => {
resolve(files)
}).then((files) => {
//do something with the files
})
答案 2 :(得分:0)
让我们从错误使用异步调用的想法开始。
首先,编写外部使用数据的函数是一个非常糟糕的主意,特别是在涉及异步时(更不用说函数处理程序)。
请刷你的异步编码知识。你应该首先让你的函数只使用传入的变量,而不是外部的任何东西(没有副作用)。虽然你的小例子最终可能会起作用,但你不能像这样建立一个好的代码库。
其次,正如其他人指出的那样,您可能正在调用GetFilesList然后打印结果。因此,对GetFilesList的调用会启动异步操作,然后函数结束(因为它存在)。但这并不意味着它完成了它打算做的事情,所以在下一行你打印ResponseData并得到它是空的惊喜。打印后,磁盘操作将完成,然后调用您的回调,此时您的数据将被填写,您的问题应该是“何时知道”或“如何等待”,直到它被填满。您正在将同步逻辑与异步逻辑混合在一起,这是完全没问题,并且最初会发生在每个人身上。
你不需要承诺来解决这个问题,承诺是首选的方式,但如果你只是开始异步编码,我个人会建议回调,直到你100%理解它然后转移到承诺。
看一下这段代码,我添加了main来试图帮助你理解这个流程。
const fs = require("fs");
function getFilesList(FolderName, callback) {
fs.readdir(FolderName, callback);
}
function main(callback) {
getFilesList(".", function(err, files) {
if(err) {
return callback(err);
}
const responseData = {str: ""};
for(const Idx in files) {
const Entry = "File " + Idx + " =" + files[Idx] + "=";
responseData.str += Entry;
console.log(Entry);
}
callback(null, responseData);
});
}
main(function(err, responseData) {
if(err) {
console.log("Error:", err);
} else {
console.log(responseData);
}
});