Rolf B: ADVANCED - promise.all in Verbindung mit decorator functions

Beitrag lesen

Hallo Rolf,

mein Vorschlag für einen Promise-Controller sähe so aus:

function getPromiseController() {
  let resolveAllDone,
      allDone = new Promise((resolve, reject) => resolveAllDone = resolve),
      pool = [];

  function complete(promise) {
    let p = pool.indexOf(promise);
    if (p >= 0)
      pool.splice(p, 1);
    if (pool.length == 0)
      resolveAllDone();
  }

  return {
    get whenDone() {
      return allDone;
    },
    watch(promise) {
      pool.push(promise);
      return promise.finally( () => complete(promise) );
    }
  };
}

let pc = getPromiseController();

pc.watch(
   new Promise(...).then(result => /* verarbeite result 1 */)
);
pc.watch(
   new Promise(...).then(result => /* verarbeite result 2 */)
);
pc.watch(
   new Promise(...).then(result => /* verarbeite result 3 */)
);

pc.whenDone.then(() => console.log("All Done"));

getPromiseController erzeugt ein Objekt mit zwei Eigenschaften: ein whenDone-Property, das ein Promise zurückgibt, das sich bei "all done" erfüllt. Und eine watch-Methode, der man ein Promise übergibt. Sobald es resolved oder rejected, wird überprüft, ob es das letzte offene Promise war. Wenn ja, wird "all done" resolved.

Wichtig ist hier, dass Du der watch-Methode das Promise übergibst, das als Ergebnis deiner eigenen then/catch-Aufrufe entsteht. Ich habe das durch die Einrückungen der watch-Aufrufe dargestellt. Die watch-Methode kann es auch anders, sie gibt das finally-Promise wieder zurück, d.h. Du kannst auch auf das Ergebnis von watch weitere then-Handler registrieren. Der Unterschied ist das Timing. Ein then innerhalb von watch wird ausgeführt, bevor "all done" ausgelöst wird. Und ein then außerhalb von watch erfolgt erst nach dem "all done".

Du musst den Parameter für watch natürlich nicht an Ort und Stelle erzeugen. Das kannst Du auch vorher tun und in eine Variable legen, oder Du rufst eine Funktion auf, die ein Promise zurückgibt. Beispielsweise eine Promise-Kapsel um setTimeout:

function delay(zeit, info) {
   return new Promise( (res, rej) => setTimeout(() => res(info), zeit));
}

pc.watch(
   delay(1000, "1s vorbei")
   .then(result => console.log("Ergebnis: " + result))
);

Rolf

--
sumpsi - posui - obstruxi