Javascript 承诺链乱序执行
Javascript promise chain executing out of order
我使用 Javascript 的原生 Promise 制作了 fs.readFile
的 "promisified" 版本,它在解析时解析 JSON 文件和 returns 对象.
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);
}
});
});
}
我首先尝试自己链接承诺,但由于某种原因,首先记录了承诺 1 中的 districts.variable1
,然后在承诺 3 中调用了 comparePersonalities
,这给出了一个错误,因为用户仍然undefined,然后 user.variable2
从 promise 2 中记录下来。
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
中做错了什么?
你必须 return 每次链接的承诺:
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
在更高范围内声明时才有效。否则一旦你到达这个函数它将是未定义的。
Promise.all
更适合您的用例。您在回调中犯了一个错误:外部承诺使用 array 结果解决(与内部承诺的顺序相同),因此 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);
});
承诺总是只用 一个 值解决。这真的很重要,而且实际上简化了很多事情,因为您总是知道期望有多少元素。
第一个例子
你犯了一个错误,你将 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
方法,因为承诺会在您的下一个函数调用中得到解决并很好地返回。
您的代码段中的问题是承诺总是解析一个对象,在 Promise.all
的情况下,您应该期待一个数组。你实际上可以使用 es6 解构来简化你的代码:
Promise.all([readFileAsync(file1), readFileAsync(file2)])
.then(function ([districts, user]) {
comparePersonalities(districts, user);
});
我使用 Javascript 的原生 Promise 制作了 fs.readFile
的 "promisified" 版本,它在解析时解析 JSON 文件和 returns 对象.
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);
}
});
});
}
我首先尝试自己链接承诺,但由于某种原因,首先记录了承诺 1 中的 districts.variable1
,然后在承诺 3 中调用了 comparePersonalities
,这给出了一个错误,因为用户仍然undefined,然后 user.variable2
从 promise 2 中记录下来。
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
中做错了什么?
你必须 return 每次链接的承诺:
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
在更高范围内声明时才有效。否则一旦你到达这个函数它将是未定义的。
Promise.all
更适合您的用例。您在回调中犯了一个错误:外部承诺使用 array 结果解决(与内部承诺的顺序相同),因此 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);
});
承诺总是只用 一个 值解决。这真的很重要,而且实际上简化了很多事情,因为您总是知道期望有多少元素。
第一个例子
你犯了一个错误,你将 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
方法,因为承诺会在您的下一个函数调用中得到解决并很好地返回。
您的代码段中的问题是承诺总是解析一个对象,在 Promise.all
的情况下,您应该期待一个数组。你实际上可以使用 es6 解构来简化你的代码:
Promise.all([readFileAsync(file1), readFileAsync(file2)])
.then(function ([districts, user]) {
comparePersonalities(districts, user);
});