Может ли генератор использовать асинхронные функции? - PullRequest
0 голосов
/ 11 сентября 2018

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

Наивная реализация:

function* getEndlessRecords(fetchingFunction) {
  const batchSize = 20;

  // endless loop:
  for (let offset = 0; true; offset += batchSize) {
    fetchingFunction(offset, batchSize)
      .then(records => {
        for (let i=0; i < records.length; i++) {
          yield records[i]; // THIS DOESN'T WORK!!!
        }
      })
  }
}

(могут быть опечатки - это упрощенный код)

Я понимаю, почему это не работает (yield работает с самой внутренней функцией), однако я не могу найти хороший способ создать генератор вокруг асинхронных функций.

Возможно ли для генератора использовать выходные данные асинхронных функций?

1 Ответ

0 голосов
/ 11 сентября 2018

Начиная с ES2018, вы можете использовать функцию асинхронного генератора :

async function* getEndlessRecords(fetchingFunction) {
  const batchSize = 20;

  // endless loop:
  for (let offset = 0; true; offset += batchSize) {
    const records = await fetchingFunction(offset, batchSize);
    for (let i=0; i < records.length; i++) {
      yield records[i];
    }
  }
}

Вы бы потребляли это в функции async, используя for-await-of (не for-of):

for await (const value of getEndlessRecords(/*...*/)) {
    // Do something with `value`
}

... или просто вызвав его next метод и ожидая результата:

let g = getEndlessRecords(/*...*/);
let result;
while (!(result = await g.next()).done) {
    console.log(result.value);
}

... или, конечно, в функции, отличной от async, вы должны использовать then для результата g.next().

До синтаксиса функции асинхронного генератора ES2018 вы должны были вручную кодировать генератор, а не использовать синтаксис function*. Делать это возможно - в правильно (без учета каких-либо расширений для % GeneratorPrototype% ) довольно легко. Делать это правильно довольно неудобно, так как % GeneratorPrototype% не имеет общедоступного символа, и вам нужно его обнаружить.

...