我使用Javascript的本机Promise创建了fs.readFile
的“promisified”版本,它解析JSON文件并在解析时返回对象。
function readFileAsync(file, options) {
return new Promise(function (resolve, reject) {
fs.readFile(file, options, function(err, data) {
if (err) {
reject(err);
} else {
var object = JSON.parse(data);
resolve(object);
}
});
});
}
我首先尝试自己链接承诺,但出于某种原因首先记录了来自promise 1的districts.variable1
,然后在promise 3中调用comparePersonalities
,这会产生错误,因为用户仍未定义,然后从promise 2中记录user.variable2
。
var user, district;
readFileAsync(file1, 'utf8').then(function (data) {
districts = data;
console.log(districts.variable1);
}).then(readFileAsync(file2, 'utf8').then(function (data) {
user = data;
console.log(user.variable2);
})).then(function (result) {
comparePersonalities(districts, user);
}).catch(function (e) {
console.log(e);
});
我还尝试了使用Promise.all
的替代方法,但这仍导致订单错误且comparePersonalities
失败。
Promise.all([readFileAsync(file1), readFileAsync(file2)]).then(function (first, second) {
districts = first;
user = second;
comparePersonalities(districts, user);
});
当在promise中记录已解析的对象时,一切似乎都运行良好,我无法弄清楚为什么一切都最终被初始化,但最后一个promise在第二个promise完成之前运行。在链式承诺和Promise.all
中我做错了什么?
答案 0 :(得分:2)
Promise.all
更适合您的用例。你在回调中犯了一个错误:外部的promise用结果的数组来解决(与内部promises的顺序相同),所以then(function (first, second) {...})
是不正确的。试试这样的事情
Promise.all([
readFileAsync(file1, 'utf8'),
readFileAsync(file2, 'utf8')
]).then(function (results) {
// note that "results" is an array of two values
var districts = results[0];
var user = results[1];
comparePersonalities(districts, user);
});
答案 1 :(得分:0)
每次链接都必须返回Promise:
readFileAsync(file1, 'utf8').then(function(data) {
districts = data;
console.log(districts.variable1);
return readFileAsync(file2, 'utf8');
}).then(function(data) {
user = data;
console.log(user.variable2);
comparePersonalities(districts, user);
}).catch(function(e) {
console.log(e);
});
只有在较高范围内声明变量comparePersonalities(districts, user)
时, districts
才有效。否则,一旦达到此功能,它将是未定义的。
答案 2 :(得分:0)
始终仅使用一个值解决Promise。这非常重要,实际上简化了很多事情,因为你总是知道要期待多少元素。
你犯了一个错误,你将Promise传递给.then
方法,而实际上它总是需要一个函数。请注意,代码段readFileAsync(file2, 'utf8')
很好地包装在匿名函数中。
var user, district;
readFileAsync(file1, 'utf8').then(function (data) {
districts = data;
console.log(districts.variable1);
})
.then(function () { return readFileAsync(file2, 'utf8') })
.then(function (data) {
user = data;
console.log(user.variable2);
}).then(function (result) {
comparePersonalities(districts, user);
}).catch(function (e) {
console.log(e);
});
但是,在这种情况下,您可能最好使用Promise.all
方法,因为承诺会在您的下一个函数调用中得到解决并很好地返回。
你的代码片段中的问题是promises总是解析一个单独的对象,而在Promise.all
的情况下,你应该期待一个单独的数组。您实际上可以使用es6解构来简化代码:
Promise.all([readFileAsync(file1), readFileAsync(file2)])
.then(function ([districts, user]) {
comparePersonalities(districts, user);
});