Fehlerbehandlung in Promise.all

264

Ich habe eine Reihe von Versprechungen, mit denen ich löse Promise.all(arrayOfPromises);

Ich setze die Versprechen-Kette fort. Sieht ungefähr so ​​aus

existingPromiseChain = existingPromiseChain.then(function() {
  var arrayOfPromises = state.routes.map(function(route){
    return route.handler.promiseHandler();
  });
  return Promise.all(arrayOfPromises)
});

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
  // do stuff with my array of resolved promises, eventually ending with a res.send();
});

Ich möchte eine catch-Anweisung hinzufügen, um ein einzelnes Versprechen zu behandeln, falls es fehlerhaft ist. Wenn ich es jedoch versuche, wird Promise.allder erste gefundene Fehler zurückgegeben (der Rest wird ignoriert), und dann kann ich die Daten aus dem Rest der Versprechen in nicht abrufen das Array (das hat keinen Fehler gemacht).

Ich habe versucht, so etwas wie ..

existingPromiseChain = existingPromiseChain.then(function() {
      var arrayOfPromises = state.routes.map(function(route){
        return route.handler.promiseHandler()
          .then(function(data) {
             return data;
          })
          .catch(function(err) {
             return err
          });
      });
      return Promise.all(arrayOfPromises)
    });

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
      // do stuff with my array of resolved promises, eventually ending with a res.send();
});

Das lässt sich aber nicht lösen.

Vielen Dank!

- -

Bearbeiten:

Was die folgenden Antworten sagten, war völlig richtig, der Code brach aus anderen Gründen. Falls jemand interessiert ist, ist dies die Lösung, die ich gefunden habe ...

Node Express-Serverkette

serverSidePromiseChain
    .then(function(AppRouter) {
        var arrayOfPromises = state.routes.map(function(route) {
            return route.async();
        });
        Promise.all(arrayOfPromises)
            .catch(function(err) {
                // log that I have an error, return the entire array;
                console.log('A promise failed to resolve', err);
                return arrayOfPromises;
            })
            .then(function(arrayOfPromises) {
                // full array of resolved promises;
            })
    };

API-Aufruf (route.async-Aufruf)

return async()
    .then(function(result) {
        // dispatch a success
        return result;
    })
    .catch(function(err) {
        // dispatch a failure and throw error
        throw err;
    });

Das Setzen des .catchfor Promise.allvor das .thenscheint den Zweck erfüllt zu haben, Fehler aus den ursprünglichen Versprechungen abzufangen, aber dann das gesamte Array zum nächsten zurückzukehren.then

Vielen Dank!

Jon
quelle
2
Ihr Versuch scheint zu funktionieren ... Vielleicht gibt es später irgendwo ein anderes Problem?
Ry-
.then(function(data) { return data; })kann komplett weggelassen werden
Bergi
Der einzige Grund, den das oben Gesagte nicht beheben sollte, ist, wenn Sie uns nicht den gesamten Code in den thenoder catchHandlern anzeigen und ein Fehler darin ausgelöst wird. Ist das übrigens dieser Knoten?
1
Sie haben keinen endgültigen Haken in Ihrer "vorhandenen Kette", daher gibt es möglicherweise Fehler, die Sie nicht sehen und die möglicherweise erklären, warum sie "nicht behoben" werden. Versuchen Sie, das hinzuzufügen, und sehen Sie, welchen Fehler Sie erhalten.
Fock
Hier ist die Antwort: stackoverflow.com/questions/31424561/…
Humoyun Ahmad

Antworten:

189

Promise.allist alles oder nichts. Es wird aufgelöst, sobald alle Versprechen im Array aufgelöst wurden, oder abgelehnt, sobald einer von ihnen ablehnt. Mit anderen Worten, es wird entweder mit einem Array aller aufgelösten Werte aufgelöst oder mit einem einzigen Fehler zurückgewiesen.

Einige Bibliotheken haben einen Namen Promise.when, von dem ich verstehe, dass er stattdessen darauf wartet, dass alle Versprechen im Array entweder aufgelöst oder abgelehnt werden, aber ich bin nicht damit vertraut und es ist nicht in ES6.

Dein Code

Ich stimme anderen hier zu, dass Ihr Fix funktionieren sollte. Es sollte mit einem Array aufgelöst werden, das eine Mischung aus erfolgreichen Werten und Fehlerobjekten enthalten kann. Es ist ungewöhnlich, Fehlerobjekte im Erfolgspfad zu übergeben, aber wenn Ihr Code sie erwartet, sehe ich kein Problem damit.

Der einzige Grund, warum ich mir vorstellen kann, warum es "nicht aufgelöst" werden kann, ist, dass der Code, den Sie uns nicht anzeigen, fehlschlägt und dass Sie keine Fehlermeldung dazu sehen, weil diese Versprechenskette nicht mit einem Finale beendet wird fangen (soweit du uns sowieso zeigst).

Ich habe mir die Freiheit genommen, die "vorhandene Kette" aus Ihrem Beispiel herauszurechnen und die Kette mit einem Haken zu beenden. Dies mag für Sie nicht richtig sein, aber für Leute, die dies lesen, ist es wichtig, immer entweder Ketten zurückzugeben oder zu beenden, da sonst potenzielle Fehler, sogar Codierungsfehler, versteckt werden (was meiner Meinung nach hier passiert ist):

Promise.all(state.routes.map(function(route) {
  return route.handler.promiseHandler().catch(function(err) {
    return err;
  });
}))
.then(function(arrayOfValuesOrErrors) {
  // handling of my array containing values and/or errors. 
})
.catch(function(err) {
  console.log(err.message); // some coding error in handling happened
});
Ausleger
quelle
4
Sie (und die obigen Kommentare) hatten Recht. Mein route.handler.promiseHandler musste .catch () und den Fehler zurückgeben. Ich musste auch das letzte .catch () am Ende der Kette hinzufügen. Vielen Dank, dass Sie die Wichtigkeit von Erfolgs- / Fehlerbehandlungsroutinen in jedem Schritt der Kette weitergeben :).
Jon
2
Ich fand auch heraus, dass, wenn ich den Fehler in meinem .catch () für route.handler.promiseHandler auslöse, er automatisch zum endgültigen Fang geht. Wenn ich stattdessen den Fehler zurückgebe, wird er das tun, was ich will, und das gesamte Array behandeln.
Jon
2
Es gibt jetzt eine Standardmethode Promise.allSettled()mit angemessener Unterstützung. Siehe Referenz .
Andréa Maugars
Ja, Promise.allschlägt fehl, wenn der erste Thread fehlschlägt. Leider laufen alle anderen Threads weiter, bis sie fertig sind. Nichts wird abgebrochen, noch schlimmer: Es gibt keine Möglichkeit, einen Thread abzubrechen Promise. Was auch immer die Threads tun (und manipulieren), sie ändern weiterhin Zustände und Variablen, sie verwenden CPU, aber am Ende geben sie ihr Ergebnis nicht zurück. Sie müssen sich dessen bewusst sein, um kein Chaos zu erzeugen, z. B. wenn Sie den Anruf wiederholen / wiederholen.
Marc Wäckerlin
142

NEUE ANTWORT

const results = await Promise.all(promises.map(p => p.catch(e => e)));
const validResults = results.filter(result => !(result instanceof Error));

FUTURE Promise API

Solominh
quelle
11
Muss eaber nicht sein Error. Es kann beispielsweise eine Zeichenfolge sein, wenn jemand sie wie folgt zurückgibt Promise.reject('Service not available').
Klesun
@ArturKlesun wie können wir dann klassifizieren, welches der Versprechen zu Fehlern führte und welches nicht?
Shubham Jain
5
@ Shubham-Jain mit .then()und .catch(). Promise.resolve()würde den Wert an den ersteren weitergeben, während Promise.reject()er an den letzteren weitergegeben wird. Sie können sie beispielsweise in ein Objekt einschließen : p.then(v => ({success: true, value: v})).catch(e => ({success: false, error: e})).
Klesun
2
Warum würden Sie die Ergebnisse filtern? Das macht keinen Sinn, wenn Sie etwas mit den Ergebnissen anfangen - Sie benötigen die Bestellung, um zu wissen, welcher zurückgegebene Wert von welchem ​​Versprechen stammt!
Ryan Taylor
21

Um die Promise.allSchleife fortzusetzen (auch wenn ein Versprechen abgelehnt wird), habe ich eine Dienstprogrammfunktion geschrieben, die aufgerufen wird executeAllPromises. Diese Dienstprogrammfunktion gibt ein Objekt mit resultsund zurück errors.

Die Idee ist, dass alle Versprechen, an die Sie weitergeben, executeAllPromisesin ein neues Versprechen verpackt werden, das immer aufgelöst wird. Das neue Versprechen wird mit einem Array mit 2 Punkten aufgelöst. Der erste Punkt enthält den Auflösungswert (falls vorhanden) und der zweite Punkt enthält den Fehler (wenn das verpackte Versprechen abgelehnt wird).

Als letzter Schritt werden executeAllPromisesalle Werte der verpackten Versprechen akkumuliert und das endgültige Objekt mit einem Array für resultsund einem Array für zurückgegeben errors.

Hier ist der Code:

function executeAllPromises(promises) {
  // Wrap all Promises in a Promise that will always "resolve"
  var resolvingPromises = promises.map(function(promise) {
    return new Promise(function(resolve) {
      var payload = new Array(2);
      promise.then(function(result) {
          payload[0] = result;
        })
        .catch(function(error) {
          payload[1] = error;
        })
        .then(function() {
          /* 
           * The wrapped Promise returns an array:
           * The first position in the array holds the result (if any)
           * The second position in the array holds the error (if any)
           */
          resolve(payload);
        });
    });
  });

  var errors = [];
  var results = [];

  // Execute all wrapped Promises
  return Promise.all(resolvingPromises)
    .then(function(items) {
      items.forEach(function(payload) {
        if (payload[1]) {
          errors.push(payload[1]);
        } else {
          results.push(payload[0]);
        }
      });

      return {
        errors: errors,
        results: results
      };
    });
}

var myPromises = [
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject(new Error('3')),
  Promise.resolve(4),
  Promise.reject(new Error('5'))
];

executeAllPromises(myPromises).then(function(items) {
  // Result
  var errors = items.errors.map(function(error) {
    return error.message
  }).join(',');
  var results = items.results.join(',');
  
  console.log(`Executed all ${myPromises.length} Promises:`);
  console.log(`— ${items.results.length} Promises were successful: ${results}`);
  console.log(`— ${items.errors.length} Promises failed: ${errors}`);
});

Benny Neugebauer
quelle
2
Dies kann einfacher gemacht werden. Siehe stackoverflow.com/a/36115549/918910
Fock
17

ES2020 führt eine neue Methode für den Promise-Typ ein: Promise.allSettled()
Promise.allSettled gibt Ihnen ein Signal, wenn alle Eingabeversprechen erfüllt sind, was bedeutet, dass sie entweder erfüllt oder abgelehnt werden. Dies ist nützlich, wenn Sie sich nicht für den Stand des Versprechens interessieren, sondern nur wissen möchten, wann die Arbeit erledigt ist, unabhängig davon, ob sie erfolgreich war.

const promises = [
  fetch('/api-call-1'),
  fetch('/api-call-2'),
  fetch('/api-call-3'),
];
// Imagine some of these requests fail, and some succeed.

const result = await Promise.allSettled(promises);
console.log(result.map(x=>s.status));
// ['fulfilled', 'fulfilled', 'rejected']

Lesen Sie mehr im v8-Blogbeitrag https://v8.dev/features/promise-combinators

MosheZada
quelle
13

Wie @jib sagte,

Promise.all ist alles oder nichts.

Sie können jedoch bestimmte Versprechen kontrollieren, die "scheitern" dürfen, und wir möchten fortfahren .then.

Beispielsweise.

  Promise.all([
    doMustAsyncTask1,
    doMustAsyncTask2,
    doOptionalAsyncTask
    .catch(err => {
      if( /* err non-critical */) {
        return
      }
      // if critical then fail
      throw err
    })
  ])
  .then(([ mustRes1, mustRes2, optionalRes ]) => {
    // proceed to work with results
  })
Ihr Mann
quelle
6

Wenn Sie die q-Bibliothek https://github.com/kriskowal/q verwenden können, verfügt sie über die q.allSettled () -Methode, mit der dieses Problem gelöst werden kann. Sie können jedes Versprechen je nach Status entweder vollständig erfüllen oder ablehnen

existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
  return route.handler.promiseHandler();
});
return q.allSettled(arrayOfPromises)
});

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
//so here you have all your promises the fulfilled and the rejected ones
// you can check the state of each promise
arrayResolved.forEach(function(item){
   if(item.state === 'fulfilled'){ // 'rejected' for rejected promises
     //do somthing
   } else {
     // do something else
   }
})
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
Mohamed Mahmoud
quelle
Da Sie die Verwendung einer Bibliothek ( q) vorschlagen , ist es nützlicher, wenn Sie ein Verwendungsbeispiel für die Frage angeben. Derzeit erklärt Ihre Antwort nicht, wie diese Bibliothek zur Lösung des Problems beitragen kann.
ishmaelMakitla
fügte ein Beispiel wie vorgeschlagen hinzu
Mohamed Mahmoud
1
Um 2018 sollte man immer sehen, was Sindre zur Verfügung hat :-). github.com/sindresorhus/p-settle . Mit Sindres Single-Purpose-Modulen müssen Sie keine große Bibliothek wie q für nur ein Bit importieren.
DKebler
6

Mit Async warten -

Hier gibt eine asynchrone Funktion func1 einen aufgelösten Wert zurück, und func2 gibt einen Fehler aus und gibt in dieser Situation eine Null zurück. Wir können damit umgehen, wie wir wollen, und entsprechend zurückgeben.

const callingFunction  = async () => {
    const manyPromises = await Promise.all([func1(), func2()]);
    console.log(manyPromises);
}


const func1 = async () => {
    return 'func1'
}

const func2 = async () => {
    try {
        let x;
        if (!x) throw "x value not present"
    } catch(err) {
       return null
    }
}

callingFunction();

Ausgabe ist - ['func1', null]

Nayan Patel
quelle
4

Für diejenigen, die ES8 verwenden und hier stolpern, können Sie mit asynchronen Funktionen Folgendes tun :

var arrayOfPromises = state.routes.map(async function(route){
  try {
    return await route.handler.promiseHandler();
  } catch(e) {
    // Do something to handle the error.
    // Errored promises will return whatever you return here (undefined if you don't return anything).
  }
});

var resolvedPromises = await Promise.all(arrayOfPromises);
Tyler Yasaka
quelle
3

Wir können die Ablehnung auf der Ebene der einzelnen Versprechen behandeln. Wenn wir also die Ergebnisse in unserem Ergebnisarray erhalten, ist der abgelehnte Array-Index undefined. Wir können mit dieser Situation nach Bedarf umgehen und die verbleibenden Ergebnisse verwenden.

Hier habe ich das erste Versprechen abgelehnt, daher ist es undefiniert, aber wir können das Ergebnis des zweiten Versprechens verwenden, das sich auf Index 1 befindet.

const manyPromises = Promise.all([func1(), func2()]).then(result => {
    console.log(result[0]);  // undefined
    console.log(result[1]);  // func2
});

function func1() {
    return new Promise( (res, rej) => rej('func1')).catch(err => {
        console.log('error handled', err);
    });
}

function func2() {
    return new Promise( (res, rej) => setTimeout(() => res('func2'), 500) );
}

Nayan Patel
quelle
Wie können Sie etwas Ähnliches tun, wenn wir async await verwenden?
Rudresh Ajgaonkar
Ich habe Ihre Frage beantwortet, bitte finden Sie den Link für die Antwort. stackoverflow.com/a/55216763/4079716
Nayan Patel
2

Hast du darüber nachgedacht Promise.prototype.finally()?

Es scheint so konzipiert zu sein, dass es genau das tut, was Sie wollen - eine Funktion ausführen, sobald alle Versprechen erfüllt (gelöst / abgelehnt) sind, unabhängig davon, ob einige der Versprechen abgelehnt wurden.

Aus der MDN-Dokumentation :

Die finally()Methode kann nützlich sein, wenn Sie nach Erfüllung des Versprechens eine Verarbeitung oder Bereinigung durchführen möchten, unabhängig vom Ergebnis.

Die finally()Methode ist dem Aufruf sehr ähnlich, .then(onFinally, onFinally)es gibt jedoch einige Unterschiede:

Wenn Sie eine Funktion inline erstellen, können Sie sie einmal übergeben, anstatt gezwungen zu sein, sie entweder zweimal zu deklarieren oder eine Variable dafür zu erstellen.

Ein endgültiger Rückruf erhält kein Argument, da es kein zuverlässiges Mittel gibt, um festzustellen, ob das Versprechen erfüllt oder abgelehnt wurde. Dieser Anwendungsfall ist genau dann vorgesehen, wenn Sie sich nicht um den Ablehnungsgrund oder den Erfüllungswert kümmern und daher keine Angabe erforderlich ist.

Im Gegensatz Promise.resolve(2).then(() => {}, () => {})(was mit undefined aufgelöst wird) Promise.resolve(2).finally(() => {})wird mit 2 aufgelöst. Ebenso wird im Gegensatz zu Promise.reject(3).then(() => {}, () => {})(was mit undefined erfüllt wird) Promise.reject(3).finally(() => {})mit 3 abgelehnt.

== Fallback ==

Wenn Ihre JavaScript-Version dies nicht unterstützt Promise.prototype.finally(), können Sie diese Problemumgehung von Jake Archibald verwenden :Promise.all(promises.map(p => p.catch(() => undefined)));

Tom Auger
quelle
1
Ja, bis Promises.allSettled()es tatsächlich implementiert ist (es wird hier von MDN dokumentiert ), Promises.all.finally()scheint dann dasselbe zu erreichen. Ich bin im Begriff, es zu versuchen ...
Jamess
@jamess Warum machst du diesen Kommentar nicht als richtige Antwort? Keine der Antworten bezieht sich auf ES6 allSettled().
Pravin
@pravin - Soweit allSettled()ich weiß , ist es (noch) nirgendwo implementiert, also möchte ich der Realität nicht voraus sein. Ich hatte Erfolg mit Promises.all(myPromiseArray).finally(), und das passt zu dieser Antwort. Sobald es allSettled()tatsächlich existiert, könnte ich es testen und herausfinden, wie es tatsächlich funktioniert. Wer weiß bis dahin, was die Browser tatsächlich implementieren werden? Es sei denn, Sie haben aktuelle Informationen zum Gegenteil ...
Jamess
@jamess Stimmt, dass es sich noch im Entwurfsstadium befindet. Allerdings scheinen die neuesten FF- und Chrome-Versionen es voll zu unterstützen. Ich bin mir nicht sicher, ob es stabil ist. Mozilla Docs Wie auch immer, der Punkt, den ich anstrebte, war, dass es viel einfacher zu finden wäre Wenn es eine Antwort als ein Kommentar war, dann ist es
dein
@pravin - Als ich meinen Kommentar veröffentlichte, wurde er nirgendwo implementiert. Ich habe gerade in Firefox und Chrome getestet: Promise.allSettledist nicht in Firefox implementiert, scheint aber in Chrome zu existieren. Nur weil Dokumente sagen, dass es implementiert ist, heißt das nicht, dass es wirklich implementiert ist. Ich werde es nicht so schnell benutzen.
Jamess
0

Wenn Sie einen Fall haben, in dem Sie sich nicht besonders um die Werte der aufgelösten Versprechen kümmern, wenn es einen Fehler gibt, Sie aber dennoch möchten, dass sie ausgeführt werden, können Sie so etwas tun, das mit den Versprechen wie gewohnt gelöst wird, wenn Sie alle haben Erfolg und lehnen die fehlgeschlagenen Versprechen ab, wenn einer von ihnen versagt:

function promiseNoReallyAll (promises) {
  return new Promise(
    async (resolve, reject) => {
      const failedPromises = []

      const successfulPromises = await Promise.all(
        promises.map(
          promise => promise.catch(error => {
            failedPromises.push(error)
          })
        )
      )

      if (failedPromises.length) {
        reject(failedPromises)
      } else {
        resolve(successfulPromises)
      }
    }
  )
}
Eric
quelle
0

Sie können Ihre Versprechen-Rückgabefunktionen jederzeit so verpacken, dass sie Fehler auffangen und stattdessen einen vereinbarten Wert (z. B. error.message) zurückgeben, sodass die Ausnahme nicht bis zur Funktion Promise.all reicht und diese deaktiviert.

async function resetCache(ip) {

    try {

        const response = await axios.get(`http://${ip}/resetcache`);
        return response;

    }catch (e) {

        return {status: 'failure', reason: 'e.message'};
    }

}
Tamir Nakar
quelle
0

Ich habe einen Weg gefunden (Problemumgehung), um dies zu tun, ohne es zu synchronisieren.

Wie bereits erwähnt, Promise.allist alles von keinem.

Also ... Verwenden Sie ein beiliegendes Versprechen, um die Entschlossenheit zu fangen und zu erzwingen.


      let safePromises = originalPrmises.map((imageObject) => {
            return new Promise((resolve) => {
              // Do something error friendly
              promise.then(_res => resolve(res)).catch(_err => resolve(err))
            })
        })
    })

    // safe
    return Promise.all(safePromises)
Juan Sebastian Contreras Aceve
quelle
0

Sie müssen wissen, wie Sie einen Fehler in Ihren Ergebnissen identifizieren können. Wenn Sie keinen erwarteten Standardfehler haben, schlage ich vor, dass Sie für jeden Fehler im catch-Block eine Transformation ausführen, die ihn in Ihren Ergebnissen identifizierbar macht.

try {
  let resArray = await Promise.all(
    state.routes.map(route => route.handler.promiseHandler().catch(e => e))
  );

  // in catch(e => e) you can transform your error to a type or object
  // that makes it easier for you to identify whats an error in resArray
  // e.g. if you expect your err objects to have e.type, you can filter
  // all errors in the array eg
  // let errResponse = resArray.filter(d => d && d.type === '<expected type>')
  // let notNullResponse = resArray.filter(d => d)

  } catch (err) {
    // code related errors
  }
Anthony Awuley
quelle
0

Nicht der beste Weg zum Fehlerprotokoll, aber Sie können immer alles auf ein Array für das VersprechenAll setzen und die resultierenden Ergebnisse in neuen Variablen speichern.

Wenn Sie graphQL verwenden, müssen Sie die Antwort unabhängig davon nachbearbeiten. Wenn die richtige Referenz nicht gefunden wird, stürzt die App ab und wird eingegrenzt, wo das Problem liegt

const results = await Promise.all([
  this.props.client.query({
    query: GET_SPECIAL_DATES,
  }),
  this.props.client.query({
    query: GET_SPECIAL_DATE_TYPES,
  }),
  this.props.client.query({
    query: GET_ORDER_DATES,
  }),
]).catch(e=>console.log(e,"error"));
const specialDates = results[0].data.specialDates;
const specialDateTypes = results[1].data.specialDateTypes;
const orderDates = results[2].data.orders;
Vincent Tang
quelle
-1

So Promise.allsoll es funktionieren. Wenn ein einzelnes Versprechen reject()vorliegt, schlägt die gesamte Methode sofort fehl.

Es gibt Anwendungsfälle, in denen man möglicherweise zulassen möchte, Promise.alldass Versprechen scheitern. Verwenden Sie dazu einfach keine reject()Aussagen in Ihrem Versprechen. Um jedoch sicherzustellen, dass Ihre App / Ihr Skript nicht einfriert, falls ein einzelnes zugrunde liegendes Versprechen keine Antwort erhält, müssen Sie eine Zeitüberschreitung festlegen.

function getThing(uid,branch){
    return new Promise(function (resolve, reject) {
        xhr.get().then(function(res) {
            if (res) {
                resolve(res);
            } 
            else {
                resolve(null);
            }
            setTimeout(function(){reject('timeout')},10000)
        }).catch(function(error) {
            resolve(null);
        });
    });
}
Ronnie Royston
quelle
Hier ist die Antwort: stackoverflow.com/questions/31424561/…
Humoyun Ahmad
Es reject()ist in Ordnung, Ihr Versprechen nicht zu verwenden , aber was ist, wenn Sie die Versprechen einer anderen Bibliothek verwenden müssen?
Dan Dascalescu
-8

Ich habe eine npm-Bibliothek geschrieben, um dieses Problem noch schöner zu lösen. https://github.com/wenshin/promiseallend

Installieren

npm i --save promiseallend

2017-02-25 neue API, es ist nicht Bruch Versprechen Prinzipien

const promiseAllEnd = require('promiseallend');

const promises = [Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)];
const promisesObj = {k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)};

// input promises with array
promiseAllEnd(promises, {
    unhandledRejection(error, index) {
        // error is the original error which is 'error'.
        // index is the index of array, it's a number.
        console.log(error, index);
    }
})
    // will call, data is `[1, undefined, 2]`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// input promises with object
promiseAllEnd(promisesObj, {
    unhandledRejection(error, prop) {
        // error is the original error.
        // key is the property of object.
        console.log(error, prop);
    }
})
    // will call, data is `{k1: 1, k3: 2}`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// the same to `Promise.all`
promiseAllEnd(promises, {requireConfig: true})
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [false, true, false]})
    // won't call
    .then(data => console.log(data))
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [true, false, false]})
    // will call, data is `[1, undefined, 2]`.
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

———————————————————————————————————

Alte schlechte API, benutze es nicht!

let promiseAllEnd = require('promiseallend');

// input promises with array
promiseAllEnd([Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)])
    .then(data => console.log(data)) // [1, undefined, 2]
    .catch(error => console.log(error.errorsByKey)) // {1: 'error'}

// input promises with object
promiseAllEnd({k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)})
    .then(data => console.log(data)) // {k1: 1, k3: 2}
    .catch(error => console.log(error.errorsByKey)) // {k2: 'error'}
Wenshin
quelle
Wie funktioniert es? Bitte zeigen und erläutern Sie Ihre Implementierung der Funktion.
Bergi
Ich schrieb eine neue gleichzeitige Logik wie Promise.all. Aber es werden alle Daten und Fehler jedes Versprechens gesammelt. Es unterstützt auch die Objekteingabe, es ist kein Punkt. Nachdem ich alle Daten und Fehler gesammelt habe, überschreibe ich die promise.thenMethode, um mit den registrierten Rückrufen umzugehen, die abgelehnt und erfüllt sind. Für Details können Sie den Code sehen
wenshin
Äh, dieser Code ruft beide onFulfilledund onRejectedHandler auf, die an übergeben werden then?
Bergi
Ja, nur wenn Versprechen Status Mix fulfilledund rejected. Aber wirklich, es verursacht ein schweres Problem, mit allen Versprechen Anwendungsfällen normal kompatibel zu sein, wie onFulfilledund onRejectedalle zurück Promise.reject()oder Promise.resolve(). Bisher ist mir nicht klar, wie ich es lösen soll. Hat jemand eine bessere Idee? Die beste Antwort für den Moment ist, dass möglicherweise keine Daten und Fehler in der Browserumgebung gefiltert werden können.
Wenshin
Müssen wir das npm-Modul mit dem Pip Python-Paketmanager installieren?
Sevenfourk