如何同时使Javascript Promise.all有趣的功能

时间:2016-06-13 13:11:26

标签: javascript parallel-processing ecmascript-6 es6-promise

根据我对Promise.all文档的理解,可以同时运行两个或更多功能,并等待所有功能完成。所以我尝试了这个:

function execute(id, max) {
    console.log('starting ' + id);

    console.time(id);
    var sum = 0;
    for(var i = 0; i < max; i ++) {
        sum += i;
    }
    console.timeEnd(id);
    return sum;
}

console.log("Declaring p1");
var p1 = Promise.resolve(() => execute("p1", 10000));
console.log("Declaring p2");
var p2 = Promise.resolve(() => execute("p2", 100000));

console.log("Calling Promise.all");
console.time("all"); 
Promise.all([p1, p2]).then((values) => console.log("Then: " + values));
console.timeEnd("all");

然而,我得到的(在Chrome中运行)是这样的:

Declaring p1
Declaring p2
Calling Promise.all
all: 0.599ms
Then: () => execute("p1", 10000),() => execute("p2", 100000)

显然,不仅函数没有像then方法那样运行,而不是结果。

即使我用原始函数调用替换promises,我也有同样的结果:

function execute(id, max) {
    console.log('starting ' + id);

    console.time(id);
    var sum = 0;
    for(var i = 0; i < max; i ++) {
        sum += i;
    }
    console.timeEnd(id);
    return sum;
}

console.log("Calling Promise.all");
console.time("all");
Promise.all([() => execute("p1", 10000), () => execute("p2", 100000)])
  .then((values) => console.log("Then: " + values));
console.timeEnd("all");

输出结果为:

Calling Promise.all
all: 0.274ms
Then: () => execute("p1", 10000),() => execute("p2", 100000)

所以,我认为我误解了Promise.all用法。如何使用Promises执行并行处理?

谢谢,

Rafael Afonso

1 个答案:

答案 0 :(得分:3)

Promise.all会在所有问题得到解决或其中一方拒绝后立即采取一系列承诺并予以解决。但是规则并不是异步的,实际上,完全相反的是:Promise executor立即执行 。因此,如果所有执行程序都是同步的,那么您的承诺链就是同步的。

也许这有助于理解它的工作原理:

function execute(id, max) {
    console.log('starting ' + id);

    console.time(id);
    var sum = 0;
    for(var i = 0; i < max; i ++) {
        sum += i;
    }
    console.timeEnd(id);
    return sum;
}

console.log("Declaring p1");
var p1 = Promise.resolve(execute(1, 10));

console.log("Declaring p2");
var p2 = new Promise((resolve, reject) => {
  console.log('setting timeout..');
  setTimeout(() => resolve(execute(2,10)), 2000);
})

console.log("Calling Promise.all");
console.time("all");
console.time('results');
Promise.all([p1,p2])
  .then((results) => { 
      console.log('all results', results); 
      console.timeEnd('results'); 
  })
  .catch(console.error.bind(console));

console.timeEnd("all"); // Promise.all returns immediately

那就是输出:

Declaring p1
starting 1
1: 0.016ms
Declaring p2
setting timeout..
Calling Promise.all
all: 0.097ms
starting 2
2: 0.002ms
all results [45, 45]
results: 2001.144ms

通常,在调用某个异步API时会使用Promises。但是,如果您真的想要异步运行自己的javascript,则需要使用Web Workers或其他东西,具体取决于您的平台。

编辑:关于Web Workers和Promises的一些快速的Google搜索,有一个好看的库promise-worker。好看,我的意思是,100%覆盖率和自动浏览器测试。如果你想走那条路,可能值得检查,甚至安装。