Async: Configuración de controladores de eventos mediante Async

Creado en 25 oct. 2016  ·  4Comentarios  ·  Fuente: caolan/async

Tengo problemas para usar async en una de mis pruebas de integración que involucra controladores de eventos. El problema es que el controlador de eventos debe configurarse (con una referencia a una devolución de llamada proporcionada de forma asíncrona) antes de que se emita el evento. Sin embargo, el código del controlador de eventos necesita una devolución de llamada adicional de inmediato.

Aquí hay un ejemplo simplificado que muestra el problema:

async.auto({
  // This needs to run first, but it will finish second
  event: [(next) => {
    emitter.once('awesome', next);
  }],

  // This needs to finish near the end
  checkResults: ['event', (results, next) => {
    assert(results.event.status == 200);
    assert(results.event.msg == 'cool');

    // Do other async stuff...
    somethingAsync(next);
  }],

  // This has to start second, but before the first one finishes
  emit: ['event', (results, next) => {
    event.emit('awesome', {msg: 'cool'}, next);
  }],

  checkEmit: ['emit', (results, next) => {
    // some sort of check that can be async
  },
], done);

event tiene que comenzar primero, pero no terminará hasta que ocurra el emit . emit necesita esperar a que event comience, pero no termine (también conocido como configurar el controlador). Por lo tanto, esto no terminará.

¿Hay alguna forma de hacer esto con la biblioteca asincrónica actual? (de manera limpia)

Aquí hay una solución que me gustaría, asumiendo que esto podría implementarse en async

async.auto({
  listen: [(next, done) => {
    client.on(done);
    return next();
  },

  ...
}, callback);

Podría usar paralelo, ejecutando los emisores y los oyentes (de los cuales puede haber varios en una prueba) como una matriz de tareas. Tomando los resultados y ejecutando las verificaciones como una segunda parte. Sin embargo, técnicamente no se requiere paralelo para iniciar las tareas en orden (aunque es probable que lo haga). Además, el código se vuelve menos plano, especialmente en configuraciones más complicadas.

question

Comentario más útil

Creo que ese es el caso de uso automático más loco que he visto por cierto: building_construction:

Todos 4 comentarios

Hola @Saevon , ¡gracias por la pregunta!

Una forma rápida y limpia de hacerlo sería:

async.auto({
    // This needs to finish near the end
  checkResults: [(next) => {
    return next(null, (results, next) => {
      assert(results.event.status == 200);
      assert(results.event.msg == 'cool');

      // Do other async stuff...
      // somethingAsync(next);
    });
  }],

  // This needs to run first, but it will finish second
  event: ['checkResults', (handler, next) => {
    emitter.once('awesome', handler.checkResults);
    return next();
  }],

  // This has to start second, but before the first one finishes
  emit: ['event', (results, next) => {
    // Should this be emitter.emit instead of event.emit?
    event.emit('awesome', {msg: 'cool'}, next);
  }],

  checkEmit: ['emit', (results, next) => {
    // the results of `checkResults` will be in `results.emit`
    // as the handler on 'awesome' was passed the `next`
    // callback from `emit`

    // some sort of check that can be async
    yourChecks(next);
  }]
}, function done(err) {
    // everything finished running, unless `err` !== `null`
});

Esencialmente, solo está intercambiando la dependencia event y checkResults , que en realidad podría ser un poco más limpia, ya que event depende del controlador en checkResults . checkResults ahora solo pasa el controlador a event .

La orden de ejecución sería:
checkResults --> event --> emit --> handler (passed to event from checkResults) --> checkEmit --> done .

Avísame si algo no está claro.

sí, eso resuelve el problema. ¡Gracias!

Creo que ese es el caso de uso automático más loco que he visto por cierto: building_construction:

Acordado. Por lo general, las devoluciones de llamada asíncronas y los emisores de eventos no se mezclan bien ...

¿Fue útil esta página
0 / 5 - 0 calificaciones