在本教程中,您将学习如何处理 promise 的错误处理。假设你有一个函数 getUserById() 返回 Promise

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

普通错误

首先,修改 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'
        });
    });
}

其次,使用 then()catch() 方法消费 Promise:

getUserById('a')
    .then(user => console.log(user.username))
    .catch(err => console.log(err));

代码将抛出错误:

Caught by try/catch Error: Invalid id argument

当您在 Promise 之外引发异常时,您必须使用 try/catch 方法捕获它:

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'
        });
    });
}

输出:

Caught by try/catch Error: Invalid id argument

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'
        });
    });
}

并消费 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}`);
}

输出:

Caught by .catch Error: Unauthorized access to the user data

如果您在 promise 抛出错误,catch() 方法将捕获它,而不是 try/catch。如果你链式调用 promise,catch() 方法将捕获 promise 中发生的任何错误。例如:

promise1
    .then(promise2)
    .then(promise3)
    .then(promise4)
    .catch(err => console.log(err));

在此示例中,如果 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}`);
}

在这个例子中,我们没有在 promise 中抛出错误,而是reject()显式地调用了。在这种情况下,该catch()方法还会处理错误。

缺少 catch() 方法

下面的示例未提供 catch() 处理 promise 内部错误的方法。它将导致运行时错误并终止程序:

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}`);
}

输出:

Uncaught (in promise) Unauthorized access to the user data

如果 promise 已解决,则可以省略 catch() 方法。将来,潜在的错误可能会导致程序意外停止。

结论

  • 在 promise 内部,catch() 方法将捕获由语句 throwreject() 引起的错误。
  • 如果发生错误并且您没有 catch() 方法,则 JavaScript 引擎会抛出运行时错误并停止程序。