Асинхронное/ожидающее назначение ключей объекта: параллельно?

Я знаю, что делаю это:

const resultA = await a()
const resultB = await b()
// code here

эффективно

a().then( resultA => {
   b().then( resultB => {
      // code here
   })
})

По сути, запускается a(), затем запускается b(). Я вложил их, чтобы показать, что и результат A, и результат B находятся в нашей области видимости; но обе функции не запускались одновременно.

Но как насчет этого:

const obj = {
  result1: await a(),
  result2: await b()
}

a() и b() выполняются одновременно?

Для справки:

const asyncFunc = async (func) => await func.call()
const results = [funcA,funcB].map( asyncFunc )

Я знаю, что здесь funcA и funcB работают одновременно.

Бонус:

Как бы вы представили назначение объекта

const obj = {
  result1: await a(),
  result2: await b()
}

используя then/обратные вызовы?


ОБНОВИТЬ:

@Bergi прав в этом ответе, это происходит последовательно. Чтобы поделиться хорошим решением для одновременной работы с объектом без необходимости собирать объект из массива, можно также использовать Bluebird следующим образом.

const obj2 = Bluebird.props(obj)

http://bluebirdjs.com/docs/api/promise.props.html


person Babakness    schedule 18.05.2017    source источник
comment
В вашем справочном примере есть синтаксическая ошибка (и из-за этого она вводит в заблуждение). Если вы используете await, вы должны сделать функцию стрелки async, и тогда становится очевидным, что они могут выполняться одновременно, потому что они представляют собой отдельную оценку функции.   -  person Bergi    schedule 18.05.2017
comment
Спасибо, что заметили, исправил.   -  person Babakness    schedule 18.05.2017
comment
Обратите внимание, что функции JS могут запускать асинхронные процессы, которые выполняются одновременно, но сами функции JS не выполняются одновременно в смысле многопоточного одновременного выполнения.   -  person nnnnnn    schedule 18.05.2017


Ответы (2)


Нет, каждый await будет останавливать выполнение до тех пор, пока обещание не будет выполнено, даже в середине выражения. Неважно, являются ли они частью одного и того же утверждения или нет.

Если вы хотите запускать их параллельно и ждать результата только один раз, вам нужно использовать await Promise.all(…). В вашем случае вы бы написали

const [result1, result2] = await Promise.all([a(), b()]);
const obj = {result1, result2};

Как бы вы представили назначение объекта с помощью then/обратных вызовов?

С временными переменными для каждого ожидаемого значения. Каждый await преобразуется в один вызов then:

a().then(tmp1 => {
  return b().then(tmp2 => {
    const obj = {
      result1: tmp1,
      result2: tmp2
    };
    return …
  });
})

Если бы мы хотели быть педантичными, нам пришлось бы разобрать создание объекта:

const tmp0 = {};
a().then(tmp1 => {
  tmp0.result1 = tmp1;
  return b().then(tmp2 => {
    tmp0.result2 = tmp2;
    const obj = tmp0;
    return …
  });
})
person Bergi    schedule 18.05.2017
comment
Ты прав! Я только что закончил писать тестовый код, чтобы попробовать приведенный выше код с помощью setTimeout, и он действительно работает последовательно. - person Babakness; 18.05.2017

a() и b() выполняются одновременно?

Нет, они идут последовательно.

Эквивалентом будет что-то вроде

a()
.then(result1 => b())
  .then(result2 => ({result1, result2}))
person Community    schedule 18.05.2017