我使用以下代码读取json文件并返回一个promise 我有两个问题
return globAsync("folder/*.json").catch(function (err) {
throw new Error("Error read: " + err);
}).map(function (file) {
return fs.readFileAsync(file, 'utf8')
.then(function (res) {
console.log("test");
return JSON.parse(res);
},
function (err) {
throw new Error("Error :" + err);
}).then(function () {
console.log("test2");
});
});
我使用控制台日志,我看到控制台打印了两次
test
test
test2
test2
为什么会发生这种情况以及如何避免它?
console.log("test2");
的地方,我需要调用事件
json解析完成后仍然返回json对象外部(调用者),当我添加最后then
它没有工作(返回的对象未定义)时,任何想法如何做到这一点对? 更新我尝试按照以下方式进行操作......
return globAsync("folder/*.json").catch(function (err) {
throw new Error("Error read: " + err);
}).map(function (file) {
return fs.readFileAsync(file, 'utf8')
.then(function (res) {
console.log("test");
JSON.parse(res); //data parse
}.catch(function (err) {
throw new Error("Error :" + err);
}
).then(function (data) {
obj.emit('ready');
return data;
}))
});
}
UPDATE2 我只需添加新的return JSON.parse(res);
即可解决问题
现在我应该如何解决第一个问题调用两次
答案 0 :(得分:0)
就像@jaromandaX所说,你可能有两个*.json
个文件。尝试打印出文件名,它应该变得更加明显。在这种情况下,.map
预计将被调用两次,每个文件一次。否则你将无法一起阅读和解析两个文件。
如果要在所有文件读取和解析完成后将其收敛到单个点,则需要在.then
之后链接另一个.map
。例如
return globAsync("folder/*.json")
.map(function(file) {
...
})
.then(function() {
obj.emit('ready');
});
编辑在评论中回答您的问题。你应该记住一些事情。
return Promise.reject(error)
。.map
中的任何拒绝都会将承诺链发送到拒绝流程。return Promise.reject(error)
,否则如果您没有返回拒绝对象,则可以将其恢复到解决流程中。如果您想单独处理每个错误,可以执行以下操作:
return globAsync("folder/*.json")
.catch(function(error) {
// TODO: Handle error
return Promise.reject(error);
})
.map(function(file) {
return fs.readFileAsync(file, 'utf8')
.catch(function(error) {
// TODO: Handle error
return Promise.reject(error);
})
.then(function(res) {
return JSON.parse(res);
});
})
.then(function() {
obj.emit('ready');
});
如果你想为glob处理一次,为了文件读取而处理一次,那么你必须更有创意。
return globAsync("folder/*.json")
.catch(function(error) {
// TODO: Handle error
return Promise.reject(error);
})
.then(function(files) {
return Promise.resolve(files)
.map(function(file) {
return fs.readFileAsync(file, 'utf8');
})
.catch(function(error) {
// TODO: Handle error once for any read error
return Promise.reject(error);
})
.map(function(res) {
// Judging by your original code, you are not handling
// parser error, so I wrote this code to behave equivalent
// to your original. Otherwise chain parse immediate after
// readFileAsync.
return JSON.parse(res);
});
})
.then(function() {
obj.emit('ready');
});