В чем разница между Promise.all и добавлением обещаний со знаком плюс? - PullRequest
3 голосов
/ 22 мая 2019

Я пытаюсь запустить несколько асинхронных функций параллельно / одновременно.

Я нашел два решения, но не знаю разницы между ними. они используют либо 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 ]

3 голосов
/ 22 мая 2019

Добавление двух ожидаемых обещаний может выполняться или не выполняться параллельно, в зависимости от того, когда вы их инициализируете.Если вы инициализируете их в самом операторе сложения, они будут выполняться последовательно;первый работает, затем, когда это сделано, второй работает.Смотри:

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()

Если сложить ожидаемые обещания вместе, чтобы они выполнялись последовательно, вы увидите, что p2 завершится раньше, чем p1.Это не тот случай.Однако, когда вы запускаете их с помощью 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.all будет чище.Хотя в вашем примере сложения двух результатов, использование Promise.all, вероятно, не принесет никаких результатов:

const result = await Promise.all([p1(), p2()]
  .then(([r1, r2]) => r1 + r2)
2 голосов
/ 22 мая 2019

Разницы нет!Всего два альтернативных способа добиться этого.

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();
1 голос
/ 22 мая 2019

A Promise - это объект, который представляет возможное завершение (или сбой) асинхронной операции и его результирующее значение .

Когда создается объект Promise (когда возвращается new Promise()), асинхронная операция уже запущена, и она будет выполняться и завершаться с успехом или неудачей, независимо от того, является ли она await илиnot.

await -ing a Promise - это просто способ выполнить следующие вещи:

  • синхронизировать асинхронную операцию с кодом, который ее запустил;без await код, запускающий асинхронную операцию, обычно завершается до асинхронной операции;await приостанавливает его до тех пор, пока асинхронная операция не завершится, а затем не возобновит его, позволяя последовательно выполнять несколько асинхронных операций (полезно, когда более поздняя операция зависит от результатов, полученных в результате операции, которая должна выполняться до нее);получить результат асинхронной операции, будь то значение (или вообще никакого значения) в случае успеха или исключение в случае ошибки.

Что касается асинхронной обработки, await p1 + await p2 имеет те же результаты, что и await p1; await p2.Обещание p1 ожидается для завершения , затем обещание p2 ожидается для завершения.Если p2 завершается до p1, await p2 возвращается немедленно.

Цель Promise.all() не в том, чтобы "выполнить обещания параллельно" ,Обещания не выполняются, это просто данные (результаты асинхронного кода).Асинхронный код, стоящий за обещаниями, выполняется и работает «параллельно», потому что это то, что асинхронный код делает по своей природе.Для этого не нужно Promise.all().

Цель Promise.all() состоит в том, чтобы создать механизм, который легко await для всех упакованных обещаний и захватывает разрешенные значения всех упакованных Promise s в одно значение (массив).

Также происходит сбой при сбое одного из обернутых Promise объектов.

Для части завершения / сбоя await p1 + await p2 большеили меньше, что эквивалентно await Promise.all([p1, p2]).

Захват и возврат разрешенных значений p1 и p2 - это отдельная история.
await p1 + await p2 работает, только если разрешенные значения p1и p2 можно объединить с помощью оператора +.Он не работает с массивами и объектами.Он не работает даже с числами, когда результаты должны комбинироваться по-другому.

...