web-dev-qa-db-ja.com

JavaScriptのエラーをキャッチする第1レベルでのPromiseの試行... catch

だから、私は私の最初のレベルのキャッチがエラーを処理するものであることを望みます。とにかく、最初のキャッチまでエラーを伝播する方法はありますか?

参照コード、(まだ)機能していません:

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);
}
35
Kirk Ouimet

新しい async/await構文 を使用すると、これを実現できます。執筆の時点では、これはすべてのブラウザでサポートされているわけではないことに注意してください。おそらく babel (または類似の何か)を使用してコードをトランスパイルする必要があります。

// 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);
  }
}
25
Edo

例外がスローされる前に関数が「戻った」ため、try-catchステートメントを使用して非同期にスローされた例外を処理することはできません。代わりに、_promise.then_および_promise.catch_メソッドを使用する必要があります。これらは、try-catchステートメントと同等の非同期メソッドを表します。

あなたがする必要があるのは、promiseを返し、別の_.catch_をそれにチェーンすることです:

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

プロミスは連鎖可能であるため、プロミスがエラーを再スローすると、次の_.catch_に委任されます。

ちなみに、throwステートメントを括弧で囲む必要はありません(_throw a_はthrow(a)と同じです)。


このコードをNode.jsで実行していて、何らかの理由でpromise関数の編集が許可されていない場合は、ドメインを使用して編集できます。ドメインは対処するのが最も簡単なものではなく、特定の状況ではいくつかの厄介なEdgeケースがあることに注意してください。 本当に必要な場合を除き、代わりにpromiseを使用することを強くお勧めします。

36
Qantas 94 Heavy

いいえ!プロミスは本質的に非同期であるため、それは完全に不可能です。例外がスローされると、try-catch句の実行が終了します(タイムトラベルはまだ発明されていません)。

代わりに、すべての関数からpromiseを返し、それらにエラーハンドラーをフックします。

5
Bergi

Promiseが確実に返されるようにする必要性がよくあり、ローカルエラーを処理してからオプションでそれを再スローする必要がほとんどあります。

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

この手法の利点((Promise.try/catch)は、簡単に見落とされる可能性のある解決/拒否の要件なしでPromiseチェーンを開始/保証し、デバッグの悪夢を生み出すことです。

2
kingdango

edo の答えを拡張するには、待機したくない非同期関数のエラーをキャッチしたい場合。関数の最後にawaitステートメントを追加できます。

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

someAsyncActionが失敗した場合、catchステートメントがそれを処理します。

1