Async: Einrichten von Ereignishandlern mit Async

Erstellt am 25. Okt. 2016  ·  4Kommentare  ·  Quelle: caolan/async

Ich habe Probleme bei der Verwendung von async in einem meiner Integrationstests, bei denen Ereignishandler beteiligt sind. Das Problem besteht darin, dass der Ereignishandler (mit einem Verweis auf einen asynchron bereitgestellten Rückruf) eingerichtet werden muss, bevor das Ereignis ausgegeben wird. Der Ereignishandlercode benötigt jedoch sofort einen zusätzlichen Rückruf.

Hier ist ein vereinfachtes Beispiel, das das Problem zeigt:

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 muss zuerst beginnen, wird aber nicht enden, bis emit auftritt. emit muss warten, bis event gestartet, aber nicht beendet wird (auch bekannt als das Einrichten des Handlers). Somit wird dies nicht beendet.

Gibt es eine Möglichkeit, dies mit der aktuellen asynchronen Bibliothek zu tun? (auf saubere Weise)

Hier ist eine Lösung, die ich gerne hätte, vorausgesetzt, dies könnte asynchron implementiert werden

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

  ...
}, callback);

Ich könnte parallel die Emitter und die Listener (von denen es mehrere in einem Test geben kann) als Array von Aufgaben verwenden. Nehmen Sie die Ergebnisse und führen Sie die Überprüfungen als zweiten Teil durch. Technisch ist jedoch keine Parallelität erforderlich, um die Aufgaben der Reihe nach zu starten (obwohl dies wahrscheinlich der Fall ist). Außerdem wird der Code weniger flach, insbesondere in komplizierteren Setups.

question

Hilfreichster Kommentar

Ich denke, das ist übrigens der verrückteste Auto-Use-Case, den ich gesehen habe :building_construction:

Alle 4 Kommentare

Hallo @Saevon , danke für die Frage!

Ein schneller und sauberer Weg, dies zu tun, wäre:

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`
});

Im Wesentlichen vertauschen Sie nur die Abhängigkeiten event und checkResults , was tatsächlich etwas sauberer sein könnte, da event vom Handler in checkResults abhängt. checkResults übergibt jetzt nur den Handler an event .

Die Ausführungsreihenfolge wäre:
checkResults --> event --> emit --> handler (passed to event from checkResults) --> checkEmit --> done .

Lassen Sie es mich wissen, wenn etwas unklar ist.

ja, das löst das Problem. Vielen Dank!

Ich denke, das ist übrigens der verrückteste Auto-Use-Case, den ich gesehen habe :building_construction:

Einverstanden. Normalerweise passen asynchrone Callbacks und Ereignisemitter nicht gut zusammen...

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

sjungwirth picture sjungwirth  ·  8Kommentare

Kikobeats picture Kikobeats  ·  28Kommentare

alexbjorlig picture alexbjorlig  ·  11Kommentare

rocketspacer picture rocketspacer  ·  8Kommentare

mvalletta picture mvalletta  ·  8Kommentare