Promise.all和使用加号添加promise之间有什么区别?

时间:2019-05-22 06:06:04

标签: javascript node.js ecmascript-6 es6-modules

我正在尝试并行/并行运行一些异步功能。

我找到了两个解决方案,但不知道它们之间的区别。他们使用Promise.all或附加符号。

如果一个函数引发异常,我也看不到检查结果的意义。

await Promise.all([asyncFunction01(), asyncFunction02()])
const [p1, p2] = await Promise.all([asyncFunction01(), asyncFunction02()])
const p1 = asyncFunction01()
const p2 = asyncFunction02()
await p1 + await p2
const p1 = asyncFunction01()
const p2 = asyncFunction02()
const result = await p1 + await p2

他们对我来说似乎都一样。它们都并行运行,并且在抛出错误的情况下会快速失败。我喜欢第三个选项,因为它看起来更整洁。

那有什么区别?我想念什么吗?

3 个答案:

答案 0 :(得分:3)

将两个等待的承诺加在一起可能会或可能不会并行运行,具体取决于您初始化它们的时间。如果您在additional语句本身中初始化它们,它们将顺序运行;第一个运行,然后完成时,第二个运行。参见:

const p1 = () => new Promise((resolve, reject) => {
  setTimeout(() => { 
    console.log('p1')
    resolve(200)
  }, 5000)
})

const p2 = () => new Promise((resolve, reject) => {
  setTimeout(() => { 
    console.log('p2')
    resolve(100)
  }, 3000)
})

async function start() {
  const result = await p1() + await p2()
  console.log(result)
  Promise.all([p1(), p2()])
}

start()

如果将等待的承诺加在一起使它们按顺序运行,您会看到p2p1之前完成。事实并非如此。但是,使用Promise.all运行它们时,您会看到p2首先完成。

正如@Kaiido在评论中指出的那样,OP显示了在等待承诺加总之前开始承诺。在这种情况下,它们将并行运行:

const P1 = () => new Promise((resolve, reject) => {
  setTimeout(() => { 
    console.log('p1')
    resolve(200)
  }, 5000)
})

const P2 = () => new Promise((resolve, reject) => {
  setTimeout(() => { 
    console.log('p2')
    resolve(100)
  }, 3000)
})

async function start() {
  const p1 = P1()
  const p2 = P2()
  const result = await p1 + await p2
  console.log(result)
}

start()

您会看到p2在p1之前完成。所以您是对的,在功能上没有区别。因此,根据您的用例,它们将完全相同。不过有些想法:

  1. 我认为Promise.all更加清晰。您是在向其他开发人员(以及您将来的自己)明确表示要让这些承诺并行运行。

  2. 有了Promise.All,您不必为每个Promise创建变量。在许多情况下,Promise.all会更清洁。尽管在您将两个结果加在一起的示例中,使用Promise.all可能不会更干净:

const result = await Promise.all([p1(), p2()]
  .then(([r1, r2]) => r1 + r2)

答案 1 :(得分:2)

没有区别!仅有两种替代方法可以实现它。

return5 = async () => new Promise(
  resolve => setTimeout(resolve.bind(null, 5),250)
);

return8 = async () => new Promise(
  resolve => setTimeout(resolve.bind(null, 8),300)
);

g = async () => {
  console.time('await +');
  p1a = return5(); // async task started here
  p2a = return8(); // async task started here
  // waiting for them to all finish here and are printed
  console.log(await p1a + await p2a);
  console.timeEnd('await +');

  console.time('Promise all');
  // async tasks started immediately when the promises are passed
  // as well as waiting for their completion here
  const [p1, p2] = await Promise.all([return5(), return8()]);
  // results are here and printed sync
  console.log(p1 + p2);
  console.timeEnd('Promise all');
}
g();

答案 2 :(得分:1)

一个Promisean object that represents the eventual completion (or failure) of an asynchronous operation, and its resulting value

创建Promise对象时(返回new Promise()时),异步操作已经开始,无论它是await,它都会成功运行或成功或失败。 -ed是否。

await-Promise只是完成这些任务的一种方式:

  • 将异步操作与启动它的代码同步;如果没有await,启动异步操作的代码通常会在异步操作之前完成; await暂停它,直到异步操作完成,然后再恢复它,从而允许连续执行多个异步操作(在以后的操作取决于必须在其之前运行的操作产生的结果时很有用);
  • 获取异步操作的结果,无论是成功的值(或根本没有值)还是错误的异常。

关于异步处理,await p1 + await p2await p1; await p2的结果相同。 p1承诺等待完成。然后 p2承诺等待完成。如果p2p1之前完成,则await p2立即返回。

Promise.all()的目的不是“并行履行承诺” 。承诺不会运行,它们只是数据(异步代码的结果)。 Promise背后的异步代码可以运行,并且可以“并行”运行,因为这是异步代码的本质。它不需要Promise.all()来完成。

Promise.all()的目的是产生一种机制,以轻松await来处理所有包装的promise,并将所有包装的Promise的已解析值捕获为单个值(数组) )。

当包装的Promise对象之一发生故障时,它也会失败。

对于完成/失败部分,await p1 + await p2大致等于await Promise.all([p1, p2])

捕获并返回p1p2的解析值是另一回事。
await p1 + await p2仅在p1p2的解析值可以使用+运算符组合的情况下才有效。它不适用于数组和对象。当结果必须以不同的方式组合时,即使使用数字也不起作用。