LoginSignup
108
86

More than 3 years have passed since last update.

async/await の例外処理まとめ

Last updated at Posted at 2018-04-12

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

まとめ

  • 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 => {}) で拾うことができる
108
86
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
108
86