我想澄清这一点,因为文件不是很清楚;

Q1: Promise.all(iterable)是按顺序还是并行处理所有的promise ?或者,更具体地说,它相当于运行链式承诺

p1.then(p2).then(p3).then(p4).then(p5)....

或者它是某种其他类型的算法,其中所有的p1, p2, p3, p4, p5等同时(并行)被调用,并且结果在所有解决(或一个拒绝)后立即返回?

问题2:如果承诺。所有的运行都是并行的,是否有一种方便的方法来运行一个可迭代对象?

注意:我不想使用Q或蓝鸟,而是所有本地ES6规格。


当前回答

请看这个示例

的承诺。全部并行工作

const { range, random, forEach, delay} = require("lodash");  
const run = id => {
    console.log(`Start Task ${id}`);
    let prom = new Promise((resolve, reject) => {
        delay(() => {
            console.log(`Finish Task ${id}`);
            resolve(id);
        }, random(2000, 15000));
    });
    return prom;
}


const exec = () => {
    let proms = []; 
    forEach(range(1,10), (id,index) => {
        proms.push(run(id));
    });
    let allPromis = Promise.all(proms); 
    allPromis.then(
        res => { 
            forEach(res, v => console.log(v));
        }
    );
}

exec();

其他回答

并行

await Promise.all(items.map(async (item) => { 
  await fetchItem(item) 
}))

优点:速度更快。所有的迭代都将启动,即使其中一个在以后失败。然而,它会“快速失败”。使用的承诺。allsettle,即使某些迭代失败,也要并行地完成所有迭代。从技术上讲,这些是并发调用,而不是并行调用。

按顺序

for (const item of items) {
  await fetchItem(item)
}

优点:循环中的变量可以在每次迭代中共享。行为类似于普通的命令式同步代码。

Promise.all(iterable)执行所有承诺吗?

不,承诺不能“执行”。它们在创建时就开始执行任务——它们只表示结果——甚至在将它们传递给Promise.all之前,您就可以并行执行所有的任务。

的承诺。一切都只等着多次承诺。它不关心它们解析的顺序,也不关心计算是否在并行运行。

是否有一种方便的方法来连续运行一个可迭代对象?

如果你已经许下承诺,除了承诺,你别无他法。All ([p1, p2, p3,…])(没有序列概念)。但是如果你确实有一个异步函数的可迭代对象,你确实可以按顺序运行它们。基本上你需要从

[fn1, fn2, fn3, …]

to

fn1().then(fn2).then(fn3).then(…)

解决方案是使用Array::reduce:

iterable.reduce((p, fn) => p.then(fn), Promise.resolve())

NodeJS不是并行运行承诺,而是并发运行,因为它是一个单线程事件循环架构。有可能通过创建一个新的子进程来利用多核CPU来并行运行。

并行Vs并发

其实,什么承诺。所做的就是,将Promise函数堆叠在适当的队列中(参见事件循环架构),并发运行它们(调用P1, P2,…),然后等待每个结果,然后解析Promise。所有的许诺都有结果。 的承诺。所有人都会在第一次承诺时失败,除非你必须自己处理拒绝。

并行和并发有一个很大的区别,第一个会在完全相同的时间在一个单独的进程中运行不同的计算,它们会按照自己的节奏进行,而另一个会一个接一个地执行不同的计算,而不需要等待前一个计算完成并同时进行,而不依赖彼此。

最后,回答你的问题,我保证。所有这些都不是并行或顺序执行,而是并发执行。

平行

请看这个例子

const resolveAfterTimeout = async i => {
  return new Promise(resolve => {
    console.log("CALLED");
    setTimeout(() => {
      resolve("RESOLVED", i);
    }, 5000);
  });
};

const call = async () => {
  const res = await Promise.all([
    resolveAfterTimeout(1),
    resolveAfterTimeout(2),
    resolveAfterTimeout(3),
    resolveAfterTimeout(4),
    resolveAfterTimeout(5),
    resolveAfterTimeout(6)
  ]);
  console.log({ res });
};

call();

通过运行代码,它将控制台“CALLED”为所有六个承诺,当他们被解决,它将控制台每6个响应超时后,在同一时间

请看这个示例

的承诺。全部并行工作

const { range, random, forEach, delay} = require("lodash");  
const run = id => {
    console.log(`Start Task ${id}`);
    let prom = new Promise((resolve, reject) => {
        delay(() => {
            console.log(`Finish Task ${id}`);
            resolve(id);
        }, random(2000, 15000));
    });
    return prom;
}


const exec = () => {
    let proms = []; 
    forEach(range(1,10), (id,index) => {
        proms.push(run(id));
    });
    let allPromis = Promise.all(proms); 
    allPromis.then(
        res => { 
            forEach(res, v => console.log(v));
        }
    );
}

exec();