ES7 Получение результата из массива промисов с помощью генератора ожидания

Учитывая массив обещаний, какой идиоматический способ получить результаты в ES7?

Вот что я хочу сделать:

async function getImports() {
  let imports = [System.import('./package1.js'), System.import('./package2.js')];
  let promises = await* imports;
  let results = [];
  await promises.forEach(val => val.then(data => results.push(data))); //seems hacky
  console.log(results); // array of 2 resolved imports
}

Результат правильный, но я все еще делаю forEach и then, чтобы превратить разрешенные промисы в результаты. Это просто не кажется мне правильным. Есть ли более чистый способ?


person Matt K    schedule 20.12.2015    source источник
comment
Разве promises уже не содержит разрешенных значений? По крайней мере, это то, что let result = await* [Promise.resolve(1), Promise.resolve(2)]; делает для меня?   -  person m90    schedule 20.12.2015
comment
Да, каждая запись в promises содержит [[PromiseValue]], но я не знаю, как получить к ним доступ без forEach и then   -  person Matt K    schedule 20.12.2015
comment
Это интересно. Я только что попробовал, что вышеперечисленное было передано babel, и это дало мне правильные значения. Что вы используете для транспиляции?   -  person m90    schedule 20.12.2015
comment
я использую Babel 6. Вы говорите, что promises возвращает результаты, а не обещания?   -  person Matt K    schedule 20.12.2015
comment
Весь смысл async/await в том, чтобы больше не использовать промисы вручную. Он скрыт за асинхронными функциями и ожидает асинхронных функций.   -  person Shanoor    schedule 20.12.2015
comment
Я запустил gist.github.com/m90/160f675da4d2abbf9685 в Babel Repl: babeljs.io/repl - здесь используется Babel 5, так что, возможно, здесь что-то изменилось.   -  person m90    schedule 20.12.2015
comment
Спасибо за суть, так что похоже, что возвращаемое значение равно [1,2], но console.log все еще возвращает обещание.   -  person Matt K    schedule 20.12.2015
comment
Я также пробовал, и это журналы [1, 2]   -  person Shanoor    schedule 20.12.2015
comment
хммм, да, ты прав, он регистрирует результат... интересно, тогда это вавилон 6...   -  person Matt K    schedule 20.12.2015
comment
да, определенно бабель 6...   -  person Matt K    schedule 20.12.2015
comment
Создан вопрос по адресу phabricator.babeljs.io/T6866. Спасибо за проверку на вменяемость!   -  person Matt K    schedule 20.12.2015
comment
Я пытаюсь использовать babeljs для компиляции простого файла js, и это похоже на попытку сотворить магию вуду: «асинхронная функция» - это неожиданный токен...   -  person Shanoor    schedule 20.12.2015


Ответы (3)


Как упоминалось в сообщении, которое вы подали, основная проблема заключается в том, что await* больше не существует и была удалена. К сожалению, в Babel 6 он неправильно выдавал синтаксическую ошибку и, по сути, обрабатывался как обычный await.

Вам нужно явно

 let [p1, p2] = await Promise.all([
          System.import('./package1.js'), System.import('./package2.js')]);
person loganfsmyth    schedule 20.12.2015
comment
о боже, жаль слышать, что это не будет продвигаться вперед, но спасибо, что дали мне знать! Если она у вас есть, не могли бы вы дать мне ссылку на esdiscuss или где она была отклонена? (эту конкретную вещь трудно найти, так как ни один движок не индексирует await*) - person Matt K; 20.12.2015
comment
Спецификация всегда лучшее место для поиска. Предлагаемый синтаксис спецификации находится на github.com/tc39/ecmascript- asyncawait/blob/master/spec/ и определяет только await UnaryExpression. - person loganfsmyth; 20.12.2015
comment
Вы можете взглянуть на метод Promise.each от bluebird, чтобы сделать этот код более выразительным bluebirdjs.com/docs/api/promise.each.html Есть веские причины использовать вспомогательные библиотеки, такие как Bluebird, даже с асинхронным ожиданием ES7. - person Filip Sobczak; 02.03.2018

Я не могу поверить, что это действительно работает, forEach действительно возвращает undefined, чего вы не можете await. Если вам нужен цикл, используйте map, чтобы получить массив (обещанных) результатов.

В вашем случае вы, кажется, ищете простой

async function getImports() {
  let promises = [System.import('./package1.js'), System.import('./package2.js')];
  let results = await Promise.all(promises)
  console.log(results);
}
person Bergi    schedule 20.12.2015

Один из способов сделать это ....

async function abc() {
    let p1 = getReviews();
    let p2 = getMenu();
    let [reviews, menu] = await results(p1, p2);
}

function results(...rest) {
    return Promise.all(rest).catch(err => console.log(err));
}
person Muhammad Umer    schedule 15.04.2018