promise 执行器函数(你传递给new Promise() 的回调函数)被设计为立即执行,因此你会立即看到你所有的console.log() 语句。
执行程序中通常发生的情况是,您启动了一些异步操作,例如 ajax 请求或异步文件 I/O 请求,然后一段时间后,该请求将调用 resolve(xxx) 以使用值解析该承诺。您现在拥有的没有异步操作,从不调用 resolve() 并且根本不应该使用 Promise,因为这里没有异步活动。
promise 不是函数。它不是“执行”的。因此,您实际上并没有像您的问题所暗示的那样创建具有承诺的延迟函数数组。你可以使用 Promise 来跟踪一些异步操作,并且当这些 Promise 通过将监听器附加到 Promise 解决时,你可以执行一些函数,但你并没有真正执行 Promise。
要承诺您正在创建工作,您需要提供作为传递给new Promise(fn) 的承诺执行器回调执行的函数。这就是执行发生的地方。 Promise 本身只是一个对象,用作某些异步操作的未来值的占位符。当执行器中的代码调用resolve(someValue) 时,会设置承诺值。或者,可以通过调用reject(someError) 来指示错误。同时,executor 函数之外的代码可以向.then() 或.catch() 注册侦听器,以侦听promise 中的状态变化(未来某个时间,当promise 满足某个值或以错误结束时)。
因此,在调用 resolve() 或 reject() 之后,适当的事件侦听器(使用 .then() 或 .catch() 注册)将触发,通知侦听代码终于有解决方案这个承诺(值或错误)。然后,该侦听代码可以处理该值或错误。
Promise.all() 接受一个承诺数组并返回一个新的主承诺,当任何一个承诺数组拒绝或当所有承诺数组都被解决时,它被一个值数组解决。它会监视所有其他承诺,并从本质上为您提供所有这些承诺的摘要。
为了模拟异步操作,我们可以将所有操作放在setTimeout() 中,然后调用resolve(),如下可运行的sn-p:
var buildPromises = function (numbers) {
var res = [];
numbers.forEach(function (num) {
var p = new Promise(function (resolve, reject) {
// this is called immediately and it starts
// an asynchronous operation that will finish later
setTimeout(function () {
var result = num * 2;
console.log("individual:", result);
// resolve the promise with our result
resolve(result);
}, Math.floor(Math.random() * 500) + 500);
});
res.push(p);
});
return Promise.all(res);
}
var numbers = [1, 2, 3, 4, 5];
buildPromises(numbers).then(function (results) {
console.log("group: ", JSON.stringify(results));
});
在运行此 sn-p 后的结果中,请注意单个 console.log() 语句可能按任何顺序(因为异步操作通常在时间上不可预测),但 Promise.all() 组结果始终保存在数组中 Promise 的原始顺序。这是Promise.all() 提供的另一项服务。
此外,它节省了使用.map() 来构建您的承诺数组的代码,因为您正在遍历一个数组并构建一个新数组,每个元素一个承诺,这正是.map() 的设计目的。你可以这样做:
var buildPromises = function (numbers) {
return Promise.all(numbers.map(function (num) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var result = num * 2;
console.log("individual:", result);
resolve(result);
}, Math.floor(Math.random() * 500) + 500);
});
}));
}
var numbers = [1, 2, 3, 4, 5];
buildPromises(numbers).then(function (results) {
console.log("group: ", JSON.stringify(results));
});