Promise 不适用于节点目录读取文件
Promise doesn't work with node-dir readfiles
我尝试使用 Nodejs 的 node-dir 模块从目录中读取文件,读取完所有文件后将它们发送到 Redis,最后关闭 Redis 连接,所以我使用了 Promise。但是,与 Redis 行的退出连接总是首先执行,"then" 子句似乎没有等到 Promise 解决,导致连接在任何持续发生之前被关闭,我可以寻求你的帮助吗?
new Promise((resolved, failed) => {
nodeDir.readFiles(dirName, options, (err, file, nextCallback) => {
if(err){throw err};
//...logics to get key&value
redisClient.set(key, value);
nextCallback();
});
resolved(); //it finally resolves
}).then(()=>{
redisClient.quit(); //this line never waits, it always executes first
})
让我们看一下与您的类似的代码块,找出这里出了什么问题:
new Promise((resolved, failed) => {
setTimeout(function(){}, 3000);
resolved();
}).then(()=>{
console.log("DONE");
})
在这种情况下,文本 "DONE" 会立即打印在控制台中。
但是,如果我们像下面这样写,我们会得到不同的东西:
new Promise((resolved, failed) => {
setTimeout(function(){
resolved();
}, 3000);
}).then(()=>{
console.log("DONE");
})
在这种情况下,"DONE" 将在 3 秒后打印到控制台。你立即解决了承诺,这就是这里出了问题的地方。一旦所有的副作用结束,就尝试解决它。希望能帮助到你。
我检查了模块 node-dir 的 API,它实际上提供了一种 readFiles 形式,它提供了一个回调,在处理完所有文件后执行,然后我修改了我的代码以在那里进行解析,终于如愿了,非常感谢@Plabon Dutta!
修改后的版本
new Promise((resolved, failed) => {
nodeDir.readFiles(dirName, (err, file, nextCallback) => {
// file handling
}, (err, files) => {
resolved(); //here does the resolve
});
}).then(()=>{
redisClient.quit();
})
这是来自 node-dir 库的 readFiles 的通用、promise-returning 版本。请注意,它唯一的工作是 return 一个在调用完成回调时得到解决的承诺。请注意,它不包含 then 块。
// a promise returning form of node-dir readFiles
// pass a file handling callback, but no completion function
function readFilesQ(dirname, options, fileCallback) {
return new Promise((resolved, failed) => {
// this invocation passes a completion function that resolves the promise
nodeDir.readFiles(dirname, options, fileCallback, (err, files) => {
err ? failed(err) : resolved(files)
});
})
}
现在您的文件处理和完成逻辑可以从外部提供,具体取决于您需要读取文件的位置的上下文。
readFilesQ(someDirname, someOptions, (err, content, next) => {
// handle content for each file, call next
}).then(files => {
// handle correct completion
}).catch(err => {
// handle error
})
我尝试使用 Nodejs 的 node-dir 模块从目录中读取文件,读取完所有文件后将它们发送到 Redis,最后关闭 Redis 连接,所以我使用了 Promise。但是,与 Redis 行的退出连接总是首先执行,"then" 子句似乎没有等到 Promise 解决,导致连接在任何持续发生之前被关闭,我可以寻求你的帮助吗?
new Promise((resolved, failed) => {
nodeDir.readFiles(dirName, options, (err, file, nextCallback) => {
if(err){throw err};
//...logics to get key&value
redisClient.set(key, value);
nextCallback();
});
resolved(); //it finally resolves
}).then(()=>{
redisClient.quit(); //this line never waits, it always executes first
})
让我们看一下与您的类似的代码块,找出这里出了什么问题:
new Promise((resolved, failed) => {
setTimeout(function(){}, 3000);
resolved();
}).then(()=>{
console.log("DONE");
})
在这种情况下,文本 "DONE" 会立即打印在控制台中。
但是,如果我们像下面这样写,我们会得到不同的东西:
new Promise((resolved, failed) => {
setTimeout(function(){
resolved();
}, 3000);
}).then(()=>{
console.log("DONE");
})
在这种情况下,"DONE" 将在 3 秒后打印到控制台。你立即解决了承诺,这就是这里出了问题的地方。一旦所有的副作用结束,就尝试解决它。希望能帮助到你。
我检查了模块 node-dir 的 API,它实际上提供了一种 readFiles 形式,它提供了一个回调,在处理完所有文件后执行,然后我修改了我的代码以在那里进行解析,终于如愿了,非常感谢@Plabon Dutta!
修改后的版本
new Promise((resolved, failed) => {
nodeDir.readFiles(dirName, (err, file, nextCallback) => {
// file handling
}, (err, files) => {
resolved(); //here does the resolve
});
}).then(()=>{
redisClient.quit();
})
这是来自 node-dir 库的 readFiles 的通用、promise-returning 版本。请注意,它唯一的工作是 return 一个在调用完成回调时得到解决的承诺。请注意,它不包含 then 块。
// a promise returning form of node-dir readFiles
// pass a file handling callback, but no completion function
function readFilesQ(dirname, options, fileCallback) {
return new Promise((resolved, failed) => {
// this invocation passes a completion function that resolves the promise
nodeDir.readFiles(dirname, options, fileCallback, (err, files) => {
err ? failed(err) : resolved(files)
});
})
}
现在您的文件处理和完成逻辑可以从外部提供,具体取决于您需要读取文件的位置的上下文。
readFilesQ(someDirname, someOptions, (err, content, next) => {
// handle content for each file, call next
}).then(files => {
// handle correct completion
}).catch(err => {
// handle error
})