我正在学习承诺,在这个例子中,我正在尝试使用Promise.all(...)创建一个可以执行的承诺数组(在原生ES6 下)。
承诺应该“启动”一个函数,该函数将传递给它的数字加倍。 我预计承诺的执行将推迟到我调用Promises.all(),但结果会立即打印出来。我错过了什么?
我希望承诺在我打电话时开始而不是尽快(如果不清楚)
var buildPromises = function(numbers) {
var res = [];
numbers.forEach(function(num) {
var p = new Promise(function(resolve, reject) {
console.log(num * 2);
});
res.push(p);
});
return res;
}
var numbers = [1, 2, 3];
var p = buildPromises(numbers);
答案 0 :(得分:3)
promise执行函数(传递给new Promise()
的回调)旨在立即执行,因此您将立即看到所有console.log()
语句。
执行程序中经常发生的事情是您启动了一些异步操作,例如ajax请求或异步文件I / O请求,然后一段时间后,该请求将调用resolve(xxx)
来解决该承诺值。你现在拥有的没有异步操作,从不调用resolve()
而且根本不应该使用promises,因为这里没有异步活动。
承诺不是一种功能。它不是“执行”的。所以,你并没有像你的问题所暗示的那样用promises创建一个延迟函数数组。您可以使用promises来跟踪一些异步操作,并且可以通过将侦听器附加到promise来解决这些promises时执行某些函数,但是您并没有真正执行promise。
为了承诺你正在创建工作,你提供了作为传递给new Promise(fn)
的promise执行者回调执行的函数。这就是执行发生的地方。 promise本身只是一个对象,用作某个异步操作的未来值的占位符。当执行程序中的代码调用resolve(someValue)
时,将设置promise值。或者,可以通过调用reject(someError)
来指示错误。同时,执行程序函数外部的代码可以使用.then()
或.catch()
注册侦听器,以侦听promise中的状态更改(将来某个时候,promise将履行某个值或以错误结束)。< / p>
因此,在调用resolve()
或reject()
之后,相应的事件侦听器(使用.then()
或.catch()
注册)将触发,通知收听代码,最终解决了这个承诺(值或错误)。然后,监听代码可以处理该值或错误。
Promise.all()
接受一个promises数组并返回一个新的主promise,当任何promise数组拒绝时,或者当所有promise数组都被解析时,它会被一个值数组解析。它会监视所有其他承诺,并基本上为您提供所有这些承诺的摘要。
要模拟异步操作,我们可以将您的所有操作放在setTimeout()
内,然后像这个runnable片段一样调用resolve()
:
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));
});
在运行此代码段后的结果中,请注意各个console.log()
语句可能处于任何顺序(因为异步操作通常在时间上无法预测),但Promise.all()
组结果始终保持不变在数组中的promises的原始顺序。这是Promise.all()
提供的另一项服务。
此外,它保存代码以使用.map()
来构建你的promises数组,因为你遍历一个数组并构建一个每个元素都有一个promise的新数组,这正是.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));
});
答案 1 :(得分:0)
你所缺少的是,Promise 是行动的结果而不是行动本身。承诺只是你现在可以坚持的一个对象,而你将来等待这个价值。
一旦调用返回Promise的函数,就会执行该操作。如果你想延迟,延迟调用函数。