Promiseのエラー処理

概要: このチュートリアルでは、Promiseにおけるエラー処理の方法を学びます。

getUserById() というPromiseを返す関数があると仮定します。

function getUserById(id) {
    return new Promise((resolve, reject) => {
        resolve({
            id: id,
            username: 'admin'
        });
    });
}Code language: JavaScript (javascript)

通常のエラー

まず、getUserById()関数を、Promiseの外部でエラーをスローするように変更します。

function getUserById(id) {
    if (typeof id !== 'number' || id <= 0) {
        throw new Error('Invalid id argument');
    }

    return new Promise((resolve, reject) => {
        resolve({
            id: id,
            username: 'admin'
        });
    });
}Code language: JavaScript (javascript)

次に、then()catch()メソッドの両方を使用してPromiseを処理します。

getUserById('a')
    .then(user => console.log(user.username))
    .catch(err => console.log(err));Code language: JavaScript (javascript)

コードがエラーをスローする

Uncaught Error: Invalid id argumentCode language: JavaScript (javascript)

Promiseの外部で例外を発生させる場合は、try/catchでキャッチする必要があります。

try {
    getUserById('a')
        .then(user => console.log(user.username))
        .catch(err => console.log(`Caught by .catch ${err}`));
} catch (error) {
    console.log(`Caught by try/catch ${error}`);
}Code language: JavaScript (javascript)

出力

Caught by try/catch Error: Invalid id argumentCode language: JavaScript (javascript)

Promise内部のエラー

getUserById()関数をPromise内部でエラーをスローするように変更します。

let authorized = false;

function getUserById(id) {
    return new Promise((resolve, reject) => {
        if (!authorized) {
            throw new Error('Unauthorized access to the user data');
        }

        resolve({
            id: id,
            username: 'admin'
        });
    });
}Code language: JavaScript (javascript)

そして、Promiseを消費します。

try {
    getUserById(10)
        .then(user => console.log(user.username))
        .catch(err => console.log(`Caught by .catch ${err}`));
} catch (error) {
    console.log(`Caught by try/catch ${error}`);
}Code language: JavaScript (javascript)

出力

Caught by .catch Error: Unauthorized access to the user dataCode language: JavaScript (javascript)

Promise内部でエラーをスローすると、try/catchではなくcatch()メソッドがそれをキャッチします。

Promiseをチェーンする場合、catch()メソッドは、どのPromiseで発生したエラーでもキャッチします。例えば

promise1
    .then(promise2)
    .then(promise3)
    .then(promise4)
    .catch(err => console.log(err));
Code language: JavaScript (javascript)

この例では、promise1、promise2、またはpromise4でエラーが発生した場合、catch()メソッドがそれを処理します。

reject()関数の呼び出し

エラーをスローすることは、次の例に示すように、reject()を呼び出すのと同じ効果があります。

let authorized = false;

function getUserById(id) {
    return new Promise((resolve, reject) => {
        if (!authorized) {
            reject('Unauthorized access to the user data');
        }

        resolve({
            id: id,
            username: 'admin'
        });
    });
}

try {
    getUserById(10)
        .then(user => console.log(user.username))
        .catch(err => console.log(`Caught by .catch ${err}`));
} catch (error) {
    console.log(`Caught by try/catch ${error}`);
}
Code language: JavaScript (javascript)

この例では、Promise内部でエラーをスローする代わりに、明示的にreject()を呼び出しました。この場合も、catch()メソッドがエラーを処理します。

catch()メソッドの欠落

次の例では、Promise内部のエラーを処理するためのcatch()メソッドが提供されていません。これにより、ランタイムエラーが発生し、プログラムが終了します。

function getUserById(id) {
    return new Promise((resolve, reject) => {
        if (!authorized) {
            reject('Unauthorized access to the user data');
        }
        resolve({
            id: id,
            username: 'admin'
        });
    });
}

try {
    getUserById(10)
        .then(user => console.log(user.username));
    // the following code will not execute
    console.log('next');

} catch (error) {
    console.log(`Caught by try/catch ${error}`);
}Code language: JavaScript (javascript)

出力

Uncaught (in promise) Unauthorized access to the user data

Promiseが解決される場合、catch()メソッドを省略できます。 将来、潜在的なエラーが発生すると、プログラムが予期せず停止する可能性があります。

まとめ

  • Promise内部では、catch()メソッドがthrowステートメントとreject()によって引き起こされたエラーをキャッチします。
  • エラーが発生し、catch()メソッドがない場合、JavaScriptエンジンはランタイムエラーを発行し、プログラムを停止します。
このチュートリアルは役に立ちましたか?