こんがらがったので、ひと通りのパターンを検証してみた。

まとめ

  • 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 => {}) で拾うことができる
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.