Как совместить генераторы ES6 с промисами

Я пытаюсь концептуально понять, как генераторы ES6 могут упростить асинхронный код. Вот надуманный пример:

  1. У меня есть функция getGitHubUser, которая принимает имя пользователя и возвращает обещание, которое в конечном итоге разрешается в информацию о пользователе github.
  2. У меня есть массив имен пользователей.
  3. Я хотел бы вызвать getGitHubUser с первым именем пользователя, и когда это обещание разрешится, я хочу вызвать getGitHubUser со следующим именем пользователя и продолжать это, пока я не переберу все имена пользователей.

У меня есть работающая реализация, но мне больше интересно, как я могу использовать генераторы, чтобы сделать это лучше.

var getGitHubUser = (user) => {
  // using jQuery's $.get
  return Promise.resolve($.get("https://api.github.com/users/" + user));
};

var usernames = ["fay-jai", "jyek", "Maestro501", "jaclyntsui"];

getGitHubUser(usernames[0])
  .then((result) => {
    console.log(result); // fay-jai
    return getGitHubUser(usernames[1]);
  })
  .then((result) => {
    console.log(result); // jyek
    return getGitHubUser(usernames[2]);
  })
  .then((result) => {
    console.log(result); // Maestro501
    return getGitHubUser(usernames[3]);
  })
  .then((result) => {
    console.log(result); // jaclyntsui
  });

person wmock    schedule 01.11.2015    source источник
comment
Не думаю, что генераторы здесь помогут. Вы можете просто перебирать массив вместо того, чтобы вручную связывать вызовы .then.   -  person Felix Kling    schedule 02.11.2015
comment
Верно ли это, если каждый последующий результат зависит от предыдущего вызова Promise? В моем примере я в настоящее время просто вывожу результат, но в случае, если следующий вызов Promise зависит от разрешения предыдущего вызова, мне нужно будет вручную связать его, верно?   -  person wmock    schedule 02.11.2015
comment
№ Пример: var p = Promise.resolve(); data.forEach(d => (p = p.then(result => someAsyncCall(d, result))));. Вы просто продолжаете вызывать p = p.then(...) в цикле. Это привязывает новое обещание к предыдущему обещанию.   -  person Felix Kling    schedule 02.11.2015
comment
Спасибо за предоставленный пример @FelixKling! В каких ситуациях генераторы могут быть полезны для асинхронного кода?   -  person wmock    schedule 02.11.2015
comment
Это может быть вам интересно: davidwalsh.name/async-generators.   -  person Felix Kling    schedule 02.11.2015
comment
связанные: генераторы ES6: обещание доходности   -  person Bergi    schedule 02.11.2015


Ответы (2)


Если вы хотите понять, как это работает, рассмотрите эту хорошую статью.

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

Q.spawn уже получил краткое описание от @user890255 в своем ответе, но есть и другие. Например, co, который мне нравится больше всего:

var request = require('superagent');
co(function* () {
  var data = [];
  for(var i = 0; i < usernames.length; i++){
    data.push(yield request.get("https://api.github.com/users/" + usernames[i]));
  }
  return data;
}).then((value) => {
  console.log(value);
}, (err) => {
   console.error(err.stack);
});

Как видите, co всегда возвращает промис, что очень удобно.

И минималистичный (полагаю, из-за небольшого размера файла) vo

var request = require('superagent');

vo(function* () {
  var data = [];
  for(var i = 0; i < usernames.length; i++){
    data.push(yield request.get("https://api.github.com/users/" + usernames[i]));
  }
  return data;
})((err, res) => {
  console.log(res);
});

Как видите, код функции-генератора почти такой же.

Ваше здоровье!

person Alexander Mikhalchenko    schedule 23.11.2015