Ich habe ein Szenario, in dem ich ein Versprechen zurückgebe. Das Versprechen wird im Wesentlichen durch eine Ajax-Anfrage ausgelöst.
Beim Ablehnen des Versprechens wird ein Fehlerdialog angezeigt, in dem ein Serverfehler vorliegt.
Wenn der Antwortcode 401 lautet, möchte ich das Versprechen weder auflösen noch ablehnen (da der Fehlerdialog bereits angezeigt wird). Ich möchte einfach zur Anmeldeseite weiterleiten.
Mein Code sieht ungefähr so aus:
function makeRequest(ur, params) {
return new Promise(function (resolve, reject) {
fetch(url, params).then((response) => {
let status = response.status;
if (status >= 200 && status < 300) {
response.json().then((data) => {
resolve(data);
});
} else {
if (status === 401) {
redirectToLoginPage();
} else {
response.json().then((error) => {
if (!error.message) {
error.message = constants.SERVER_ERROR;
}
reject({ status, error });
});
}
}
});
});
}
Wie Sie sehen können, leite ich bei einem Status von 401 zur Anmeldeseite weiter. Das Versprechen wird weder gelöst noch abgelehnt.
Ist dieser Code in Ordnung oder gibt es einen besseren Weg, dies zu erreichen?
quelle
reject
undresolve
Funktionen, und nicht nur stoppen , das Versprechen zu verweisen. Dann sollte GC eingreifen. Andernfalls, wenn Ihr Code beispielsweise immer noch referenziertresolve
, muss das Versprechen bestehen bleiben, falls Ihr Code jemals aufruftresolve()
. Hier ist ein Beispiel für eine Web-API, die VersprechenIch denke, das "Was passiert, wenn wir die Ablehnung nicht lösen" wurde gut beantwortet - Sie haben die Wahl, ob Sie ein
.then
oder ein hinzufügen möchten.catch
.Allerdings ist dieser Code in Ordnung? Oder gibt es einen besseren Weg , dies zu erreichen . Ich würde sagen, es gibt zwei Dinge:
new Promise
Wenn Sie ein Versprechen einpacken, wenn es nicht erforderlich ist und derfetch
Anruf fehlschlagen kann , sollten Sie darauf reagieren, damit Ihre aufrufende Methode nicht auf ein Versprechen wartet, das niemals gelöst wird.Hier ist ein Beispiel (ich denke, dies sollte für Ihre Geschäftslogik funktionieren, nicht 100% sicher):
const constants = { SERVER_ERROR: "500 Server Error" }; function makeRequest(url,params) { // fetch already returns a Promise itself return fetch(url,params) .then((response) => { let status = response.status; // If status is forbidden, redirect to Login & return nothing, // indicating the end of the Promise chain if(status === 401) { redirectToLoginPage(); return; } // If status is success, return a JSON Promise if(status >= 200 && status < 300) { return response.json(); } // If status is a failure, get the JSON Promise, // map the message & status, then Reject the promise return response.json() .then(json => { if (!json.message) { json.message = constants.SERVER_ERROR; } return Promise.reject({status, error: json.message}); }) }); } // This can now be used as: makeRequest("http://example", {}) .then(json => { if(typeof json === "undefined") { // Redirect request occurred } console.log("Success:", json); }) .catch(error => { console.log("Error:", error.status, error.message); })
Im Gegensatz dazu rufen Sie Ihren Code auf mit:
makeRequest("http://example", {}) .then(info => console.log("info", info)) .catch(err => console.log("error", err));
Protokolliert nichts, da der Aufruf von
http://example
fehlschlägt, dercatch
Handler jedoch niemals ausgeführt wird.quelle
Wie andere sagten, ist es wahr, dass es nicht wirklich ein Problem ist, wenn Sie ein Versprechen nicht lösen / ablehnen. Auf jeden Fall würde ich Ihr Problem etwas anders lösen:
function makeRequest(ur,params) { return new Promise(function(resolve,reject) { fetch(url,params) .then((response) => { let status = response.status; if (status >= 200 && status < 300) { response.json().then((data) => { resolve(data); }) } else { reject(response); } }) }); } makeRequest().then(function success(data) { //... }, function error(response) { if (response.status === 401) { redirectToLoginPage(); } else { response.json().then((error) => { if (!error.message) { error.message = constants.SERVER_ERROR; } //do sth. with error }); } });
Das heißt, ich würde jeden schlechten Antwortzustand ablehnen und dies dann in Ihrem
error handler
von Ihnen behandelnmakeRequest
.quelle
Es funktioniert und ist nicht wirklich ein Problem, außer wenn ein Anrufer
makeRequest
erwartet, dass das Versprechen erfüllt wird. Sie brechen dort also den Vertrag.Stattdessen können Sie das Versprechen verschieben oder (in diesem Fall) mit Statuscode / Fehler ablehnen.
quelle
Die ECMAScript-Spezifikation erklärt den Zweck von Versprechungen und
new Promise()
:Sie sollten Versprechen verwenden, um zukünftige Werte zu erhalten. Um Ihren Code präzise und direkt zu halten, sollten Sie außerdem nur Versprechen verwenden, um zukünftige Werte zu erhalten, und keine anderen Dinge tun.
Da Sie auch den Programmsteuerungsfluss (Umleitungslogik) in die "Executor" -Logik Ihres Versprechens gemischt haben, ist Ihr Versprechen nicht länger "ein Platzhalter für die Ergebnisse einer Berechnung". Vielmehr handelt es sich jetzt um ein kleines JavaScript-Programm, das sich als Versprechen tarnt.
Anstatt dieses JavaScript-Programm in a zu verpacken
new Promise()
, empfehle ich, es einfach wie ein normales JavaScript-Programm zu schreiben:async function makeRequest(url, params) { let response = await fetch(url, params); let { status } = response; if (status >= 200 && status < 300) { let data = await response.json(); successLogic(data); } else if (status === 401) { redirectToLoginPage(); } else { let error = await response.json() if (!error.message) { error.message = constants.SERVER_ERROR; } errorLogic({ status, error }); } }
quelle