我有一个文件,我在写东西:
var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
names.forEach(function(name){
doSomething(name);
});
stream.end();
});
这工作正常,我可以写入文件。 问题是doSomething()函数有一些异步的部分。可以使用dnsLookup函数给出一个示例。在我的doSomething()的某处,我有:
dns.lookup(domain, (err, addresses, family) => {
if(err){
stream.write("Error:", err);
}else{
stream.write(addresses);
}
});
现在,我的问题是,由于DNS检查是异步的,代码会继续执行关闭流。当DNS响应最终到来时,它无法写入任何地方。 我已经尝试使用异步模块,但它不起作用。可能我做错了什么。
有什么想法吗?
答案 0 :(得分:2)
现在NodeJS大部分时间都在使用ES2015功能(我注意到你至少使用了一个箭头功能),你可以使用JavaScript中的原生承诺(之前你可以使用一个库):
var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
Promise.all(names.map(name => doSomething(name)))
.then(() => {
// success handling
stream.end();
})
.catch(() => {
// error handling
stream.end();
});
});
(如果您知道 Promise.all(names.map(name => doSomething(name)))
忽略额外的参数并仅使用第一个参数,则行Promise.all(names.map(doSomething))
可以只是doSomething
。
Promise.all
(spec | MDN)接受一个iterable,并返回一个在迭代中的所有promise都已解决时结算的promise(非promise值被视为已解析)承诺使用该值作为分辨率。)
doSomething
变为:
function doSomething(name) {
return new Promise((resolve, reject) => {
dns.lookup(domain, (err, addresses, family) => {
if(!err){ // <== You meant `if (err)` here, right?
stream.write("Error:", err);
reject(/*...reason...*/);
}else{
stream.write(addresses);
resolve(/*...possibly include addresses*/);
});
});
});
有各种各样的库将为你“承诺 - 如果”节点式回调,所以使用promises比上面的混合更少笨重;在这种情况下,您可以直接使用承诺dns.lookup
的承诺,而不是创建自己的额外承诺。