Как я могу использовать генератор событий в качестве асинхронного генератора - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь использовать аккуратный синтаксис асинхронного генератора с babel (я застрял с узлом 8), и мне интересно, как бы вы преобразовали генератор событий в асинхронный генератор чисто

То, что я получил до сих пор, выглядит так

    const { EventEmitter } = require('events')

    // defer fonction for resolving promises out of scope
    const Defer = () => {
      let resolve
      let reject
      let promise = new Promise((a, b) => {
        resolve = a
        reject = b
      })
      return {
        promise,
        reject,
        resolve
      }
    }


    // my iterator function
    function readEvents(emitter, channel) {
      const buffer = [Defer()]
      let subId = 0

      emitter.on(channel, x => {
        const promise = buffer[subId]
        subId++
        buffer.push(Defer())
        promise.resolve(x)
      })

      const gen = async function*() {
        while (true) {
          const val = await buffer[0].promise
          buffer.shift()
          subId--
          yield val
        }
      }

      return gen()
    }

    async function main () {
      const emitter = new EventEmitter()
      const iterator = readEvents(emitter, 'data')

      // this part generates events
      let i = 0
      setInterval(() => {
        emitter.emit('data', i++)
      }, 1000)

      // this part reads events
      for await (let val of iterator) {
        console.log(val)
      }
    }

    main()

Это способ ИМО, поэтому я спрашиваю, есть ли у кого-нибудь идеи по упрощению этого

1 Ответ

0 голосов
/ 10 декабря 2018

Допустим, мы используем redux-saga (так как он использует генератор в своей основе) и socket.io в качестве примера EventEmitter

import { call, put } from 'redux-saga/effects';

function* listen() {
  yield (function* () {
    let resolve;
    let promise = new Promise(r => resolve = r); // The defer

    socket.on('messages created', message => {
      console.log('Someone created a message', message);
      resolve(message); // Resolving the defer

      promise = new Promise(r => resolve = r); // Recreate the defer for the next cycle
    });

    while (true) {
      const message = yield promise; // Once the defer is resolved, message has some value
      yield put({ type: 'SOCKET_MESSAGE', payload: [message] });
    }
  })();
}

export default function* root() {
    yield call(listen);
}

Приведенная выше настройка должна предоставить вам генератор, заблокированный следующим событием, которое будет отправлено отправителем события (экземпляр socket.io).

Ура!

...