失敗時に例外をスローすることを期待する非同期関数があります。しかし、何かがこれを妨げるようです:
try catchブロックを省略することにより、関数の外部で処理したい例外がスローされることを期待しています。
私が得る実際の結果はやや混乱しています:
(node:10636) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): E11000 duplicate key error index.
(node:10636) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
async f(obj) {
await db.collection('...').save(obj);
}
例外をキャッチして、代わりに他の何かをスローしようとすると、同じ結果が得られます。
async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
throw e.message;
}
}
この関数はtryブロックから呼び出されるので、これが未処理の約束であることはわかりません。
f
を別の関数のパラメーターとして使用しようとしています。
g(obj, handler) {
try {
handler(obj);
} catch(e);
...
}
}
g(objToSave, f);
最終的に、あなたがしようとしているのは、非同期関数f
を同期関数g
で呼び出すことです。同期関数へ)。
代わりに、g
はasync
でなければならないか、f
によって返されるプロミスを適切に処理する必要があります。ただし、 このコメントでf
で表される関数は常にプロミスを返すとは限らないと述べています。その場合、前者のオプションが最も簡単に実装できます。
async g(obj, handler) {
return await handler(obj);
}
これは、handler
がpromiseを返さず、単なる値(ドキュメント化されている here )でも機能します。
g
を(再度)呼び出すには、非同期関数、または返されたプロミスを処理するコードのいずれかが必要です。
g(objToSave, f).then(...).catch(...)
_async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
throw e.message;
}
}
_
この関数はtryブロックから呼び出されるので、これが未処理の約束であることはわかりません。
ここで処理されないのは、f()
メソッドではなく、.save()
関数によって返されるプロミスの拒否です。したがって、これはその問題を引き起こしません:
_async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
console.error(e.message);
}
}
_
非同期関数で例外をスロー常に約束を拒否する返されるその関数によって。
例外をキャッチするには、別の非同期関数でこれを行う必要があります。
_try {
asyncFunc();
} catch (err) {
// you have the error here
}
_
または、拒否ハンドラを明示的に追加できます。
_asyncFunc().catch(err => {
// you have the error here
});
_
例外をキャッチして別の例外をスローしている場合、異なる関数で同じ問題が発生します。
約束の拒否ハンドラーを追加して例外をスローしたり、拒否された約束をそこに返さないようにするか、同じ関数または新しい例外を再スローする代わりに、例外を処理する別の非同期関数でその関数を実行する必要があります。
まとめると:Every async
関数はpromiseを返します。すべてのプロミスには拒否ハンドラが必要です。
拒否ハンドラーは、2つの関数.then()
を使用して、または.catch()
で、またはtry { await asyncFunction(); } catch (err) { ... }
で追加されます。
拒否ハンドラーなしでプロミスを拒否すると、古いバージョンのNodeで警告が表示され、新しいバージョンのNode-を参照してください。詳細については、この回答:
関数の外で処理したい
それはあなたがするのを忘れた唯一のことです。 (警告が未処理拒否について文句を言っている理由です)。関数f
は正常に機能しています。
async function
から同期例外をスローすることはできません。すべてが非同期であり、例外は結果プロミスの拒否につながります。それはあなたがキャッチする必要があるものです:
function g(obj, handler) {
try {
Promise.resolve(handler(obj)).catch(e => {
console.error("asynchronous rejection", e);
});
} catch(e) {
console.error("synchronous exception", e);
}
}
// or just
async function g(obj, handler) {
try {
await handler(obj);
// ^^^^^
} catch(e) {
console.error("error", e);
}
}
g(objToSave, f);