构建一个延迟函数数组(promises)?

时间:2017-01-21 20:53:08

标签: javascript ecmascript-6

我正在学习承诺,在这个例子中,我正在尝试使用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); 

2 个答案:

答案 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的函数,就会执行该操作。如果你想延迟,延迟调用函数。