こんがらがったので、ひと通りのパターンを検証してみた。
まとめ
- async function をただ呼び出すときは
try catch
は意味をなさない -
await
付きで呼び出せばtry catch
が意味をなす -
await
の有無にかかわらず.catch(e => {})
で拾うことができる
確認環境
- Node.js
- v8.9.4
基本(例外なしの挙動)
// 100ms 後に resolve される Promise を返す
const asyncFunction = (v) => new Promise(r => setTimeout(() => r(v), 100));
const nothing = async () => {
asyncFunction('nothing');
};
const justReturn = async () => {
return asyncFunction('just return');
};
const returnWithAwait = async () => {
return await asyncFunction('return with await');
};
(async () => {
console.log(nothing());
console.log(justReturn());
console.log(returnWithAwait());
console.log(await nothing());
console.log(await justReturn());
console.log(await returnWithAwait());
})();
実行結果
Promise { undefined }
Promise { <pending> }
Promise { <pending> }
undefined
just return
return with await
async function は Promise を返す。
async function 内での await の有無は影響しない。
async function 内での例外処理
// 100ms 後に reject される Promise を返す
const asyncFunction = (v) => new Promise((_, r) => setTimeout(() => r(v), 100));
const nothing = async () => {
asyncFunction('nothing');
};
const justAwait = async () => {
await asyncFunction('just await');
};
const justTryCatch = async () => {
try {
asyncFunction('just try catch');
} catch (e) {
console.error(e);
}
}
const tryCatchWithAwait = async () => {
try {
await asyncFunction('try catch with await');
} catch (e) {
console.error(e);
}
}
const justCatch = async () => {
return asyncFunction('just catch').catch(e => console.error(e));
}
const awaitCatch = async () => {
return await asyncFunction('await catch').catch(e => console.error(e));
}
nothing();
justAwait();
justTryCatch();
tryCatchWithAwait();
justCatch();
awaitCatch();
実行結果
just catch
await catch
try catch with await
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): nothing
(node:1) [DEP0018] 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.
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): just try catch
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): just await
※エラーにならずにに文字列を出力できているものは、例外を拾うことができている、という認識。以下同様。
await
付きで呼び出して try catch
するか、 .catch()
するかで例外を拾うことができる。
.catch()
するときは、await
の有無は影響しない。
async function を呼び出す側の例外処理
先ほどの例で、例外を拾えていなかったものが対象。
// 100ms 後に reject される Promise を返す
const asyncFunction = (v) => new Promise((_, r) => setTimeout(() => r(v), 100));
const nothing = async () => {
asyncFunction('nothing');
};
const justAwait = async () => {
await asyncFunction('just await');
};
const justTryCatch = async () => {
try {
asyncFunction('just try catch');
} catch (e) {
console.error(e);
}
}
//----------------
// just try catch
//----------------
try {
nothing();
} catch (e) {
console.error('just try catch: ' + e);
}
try {
justAwait();
} catch (e) {
console.error('just try catch: ' + e);
}
try {
justTryCatch();
} catch (e) {
console.error('just try catch: ' + e);
}
//------------
// just catch
//------------
nothing().catch(e => console.error('just catch: ' + e));
justAwait().catch(e => console.error('just catch: ' + e));
justTryCatch().catch(e => console.error('just catch: ' + e));
(async () => {
//----------------------
// try catch with await
//----------------------
try {
await nothing();
} catch (e) {
console.error('try catch with await: ' + e);
}
try {
await justAwait();
} catch (e) {
console.error('try catch with await: ' + e);
}
try {
await justTryCatch();
} catch (e) {
console.error('try catch with await: ' + e);
}
//-------------
// await catch
//-------------
await nothing().catch(e => console.error('await catch: ' + e));
await justAwait().catch(e => console.error('await catch: ' + e));
await justTryCatch().catch(e => console.error('await catch: ' + e));
})();
実行結果
just catch: just await
try catch with await: just await
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): nothing
(node:1) [DEP0018] 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.
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): just try catch
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): nothing
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): just try catch
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 5): nothing
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 6): just await
await catch: just await
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 7): just try catch
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 8): nothing
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 9): just try catch
次のような場合のみ例外を拾える。
const justAwait = async () => {
await asyncFunction('just await');
};
// 以下のどれか
justAwait().catch(e => {});
(async () => {
try {
await justAwait();
} catch (e) {
}
await justAwait().catch(e => {});
})();
まとめ(再掲)
- async function をただ呼び出すときは
try catch
は意味をなさない -
await
付きで呼び出せばtry catch
が意味をなす -
await
の有無にかかわらず.catch(e => {})
で拾うことができる