web-dev-qa-db-de.com

Fehler in JavaScript abfangen Versprechen mit einem First Level try ... catch

Ich möchte also, dass mein erster Level-Catch derjenige ist, der den Fehler behandelt. Gibt es sowieso meinen Fehler bis zu diesem ersten Fang zu verbreiten?

Referenzcode, der (noch) nicht funktioniert:

Promise = require('./framework/libraries/bluebird.js');

function promise() {
    var promise = new Promise(function(resolve, reject) {
        throw('Oh no!');
    });

    promise.catch(function(error) {
        throw(error);
    });
}

try {   
    promise();
}
// I WANT THIS CATCH TO CATCH THE ERROR THROWN IN THE PROMISE
catch(error) {
    console.log('Caught!', error);
}
25
Kirk Ouimet

Mit der neuen async/await-Syntax können Sie dies erreichen. Bitte beachten Sie, dass dies zum Zeitpunkt des Schreibens nicht von allen Browsern unterstützt wird. Möglicherweise müssen Sie Ihren Code mit babel (oder ähnlichem) transpilieren.

// Because of the "async" keyword here, calling getSomeValue()
// will return a promise.
async function getSomeValue() {
  if (somethingIsNotOk) {
    throw new Error('uh oh');
  } else {
    return 'Yay!';
  }
}

async function() {
  try {
    // "await" will wait for the promise to resolve or reject
    // if it rejects, an error will be thrown, which you can
    // catch with a regular try/catch block
    const someValue = await getSomeValue();
    doSomethingWith(someValue);
  } catch (error) {
    console.error(error);
  }
}
15
Edo

Sie können try-catch-Anweisungen nicht verwenden, um asynchron ausgelöste Ausnahmen zu behandeln, da die Funktion "zurückgegeben" wird, bevor eine Ausnahme ausgelöst wird. Verwenden Sie stattdessen die Methoden promise.then und promise.catch, die das asynchrone Äquivalent der try-catch-Anweisung darstellen.

Was Sie tun müssen, ist, das Versprechen zurückzugeben und dann einen weiteren .catch daran zu verketten:

function promise() {
    var promise = new Promise(function(resolve, reject) {
        throw('Oh no!');
    });

    return promise.catch(function(error) {
        throw(error);
    });
}

promise().catch(function(error) {
    console.log('Caught!', error);
});

Versprechungen sind kettenbar, dh, wenn ein Versprechen einen Fehler zurückgibt, wird es an den nächsten .catch delegiert.

Übrigens müssen Sie keine throw-Anweisungen in Klammern verwenden (throw a ist das gleiche wie throw(a)).


Wenn Sie diesen Code in Node.js ausführen und aus irgendeinem Grund die promise-Funktion nicht bearbeiten dürfen, können Sie dazu Domains verwenden. Beachten Sie, dass Domänen nicht gerade die einfachsten Dinge sind, mit denen Sie umgehen können, und dass es unter bestimmten Umständen zu nervigen Edge-Fällen kommt. Wenn Sie nicht wirklich müssen, würde ich empfehlen, stattdessen Versprechen zu verwenden.

25
Qantas 94 Heavy

Nein! Das ist völlig unmöglich, da Versprechen von Natur aus asynchron sind. Die try-catch-Klausel hat die Ausführung beendet, wenn die Ausnahme ausgelöst wird (und Zeitreisen sind noch nicht erfunden worden).

Bringen Sie stattdessen Versprechen von allen Ihren Funktionen zurück und haken Sie einen Fehlerbehandler an.

5
Bergi

Ich finde oft die Notwendigkeit, sicherzustellen, dass ein Versprechen zurückgegeben wird, und fast genauso oft muss ein lokaler Fehler behandelt und dann optional erneut ausgegeben werden. 

function doSomeWork() {
  return Promise.try(function() {

    return request.get(url).then(function(response) {
      // ... do some specific work
    });

  }).catch(function(err) {
    console.log("Some specific work failed", err);
    throw err; // IMPORTANT! throw unless you intend to suppress the error
  });
}

Der Vorteil dieser Technik (Promise.try/catch) besteht darin, dass Sie eine Promise-Kette ohne die erforderliche Anforderung zum Ermitteln/Ablehnen starten/sicherstellen, die leicht übersehen werden kann, und einen Albtraum für das Debugging schafft.

2
kingdango

Um die Antwort von edo zu erweitern, wenn Sie die Fehler einer asynchronen Funktion abfangen möchten, auf die Sie nicht warten möchten. Sie können am Ende Ihrer Funktion eine wait-Anweisung hinzufügen.

(async function() {
  try {
    const asyncResult = someAsyncAction();

    // "await" will wait for the promise to resolve or reject
    // if it rejects, an error will be thrown, which you can
    // catch with a regular try/catch block
    const someValue = await getSomeValue();
    doSomethingWith(someValue);

    await asyncResult;
  } catch (error) {
    console.error(error);
  }
})();

Wenn someAsyncAction fehlschlägt, wird die catch-Anweisung damit umgehen.

0