欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > Promise、async、await 、异步生成器的错误处理方案

Promise、async、await 、异步生成器的错误处理方案

2024/10/27 4:57:25 来源:https://blog.csdn.net/qq_24956515/article/details/143259638  浏览:    关键词:Promise、async、await 、异步生成器的错误处理方案

1、Promise.all 的错误处理

Promise.all 方法接受一个 Promise 数组,并返回所有解析 Promise 的结果数组:

const promise1 = Promise.resolve("one");
const promise2 = Promise.resolve("two");Promise.all([promise1, promise2]).then((results) => console.log(results));// 结果: ['one', 'two']

如果这些 Promise 中的任何一个被拒绝,Promise.all 将拒绝并返回第一个被拒绝的 Promise 的错误。

为了在 Promise.all 中处理这些情况,可以使用 catch:

const promise1 = Promise.resolve("good");
const promise2 = Promise.reject(Error("Bad"));
const promise3 = Promise.reject(Error("Bad+"));Promise.all([promise1, promise2, promise3]).then(results => console.log(results)).catch(error => console.error(error.message));

如果想要运行一个函数而不考虑 Promise.all 的结果,可以使用 finally:

Promise.all([promise1, promise2, promise3]).then(results => console.log(results)).catch(error => console.error(error.message)).finally(() => console.log("Finally"));

2、Promise.any 的错误处理

Promise.any 和 Promise.all 恰恰相反。Promise.all 如果某一个失败,就会抛出第一个失败的错误。而 Promise.any 总是返回第一个成功的 Promise,无论是否发生任何拒绝。

相反,如果传递给 Promise.any 的所有 Promise 都被拒绝,那产生的错误就是 AggregateError。 来看下面的例子:

const promise1 = Promise.reject(Error("Error"));
const promise2 = Promise.reject(Error("Error+"));Promise.any([promise1, promise2]).then(result => console.log(result)).catch(error => console.error(error)).finally(() => console.log("Finally"));

输出结果如下:

fileOf7174.png

这里用 catch 处理错误。AggregateError 对象具有与基本错误相同的属性,外加一个 errors 属性:

const promise1 = Promise.reject(Error("Error"));
const promise2 = Promise.reject(Error("Error+"));Promise.any([promise1, promise2]).then(result => console.log(result)).catch(error => console.error(error.errors)).finally(() => console.log("Finally"));

此属性是一个包含所有被拒绝的错误信息的数组:

fileOf7174.png

3、Promise.race 的错误处理

Promise.race 接受一个 Promise 数组,并返回第一个成功的 Promise 的结果:

const promise1 = Promise.resolve("one");
const promise2 = Promise.resolve("two");Promise.race([promise1, promise2]).then(result => console.log(result)
);// 结果:one

那如果有被拒绝的 Promise,但它不是传入数组中的第一个呢:

const promise1 = Promise.resolve("one");
const rejection = Promise.reject(Error("Bad"));
const promise2 = Promise.resolve("two");Promise.race([promise1, rejection, promise2]).then(result =>console.log(result)
);// 结果:one

这样结果还是 one,不会影响正常的执行。

如果被拒绝的 Promise 是数组的第一个元素,则 Promise.race 拒绝,就必须要必须捕获拒绝:

const promise1 = Promise.resolve("one");
const rejection = Promise.reject(Error("Bad"));
const promise2 = Promise.resolve("two");Promise.race([rejection, promise1, promise2]).then(result => console.log(result)).catch(error => console.error(error.message));// Bad

4、Promise.allSettled 的错误处理

Promise.allSettled 是 ECMAScript 2020 新增的 API。它和 Promise.all 类似,不过不会被短路,也就是说当 Promise 全部处理完成后,可以拿到每个 Promise 的状态, 而不管其是否处理成功。

来看下面的例子:

const promise1 = Promise.resolve("Good!");
const promise2 = Promise.reject(Error("Bad!"));Promise.allSettled([promise1, promise2]).then(results => console.log(results)).catch(error => console.error(error)).finally(() => console.log("Finally"));

这里向 Promise.allSettled 传递了一个包含两个 Promise 的数组:一个已解决,另一个已拒绝。

输出结果如下:

fileOf7174.png

5、async/await 的错误处理

JavaScript 中的 async/await 表示异步函数,用同步的方式去编写异步,可读性更好。

下面来改编上面的同步函数 toUppercase,通过将 async 放在 function 关键字之前将其转换为异步函数:

async function toUppercase(string) {if (typeof string !== "string") {throw TypeError("Expected string");}return string.toUpperCase();
}

只需在 function 前加上 async 前缀,就可以让函数返回一个 Promise。这意味着我们可以在函数调用之后链式调用 then、catch 和 finally:

toUppercase("hello").then(result => console.log(result)).catch(error => console.error(error.message)).finally(() => console.log("Always runs!"));

当从 async 函数中抛出异常时,异常会成为底层 Promise 被拒绝的原因。任何错误都可以从外部用 catch 拦截。

除此之外,还可以使用 try/catch/finally 来处理错误,就像在同步函数中一样。

例如,从另一个函数 consumer 中调用 toUppercase,它方便地用 try/catch/finally 包装了函数调用:

async function toUppercase(string) {if (typeof string !== "string") {throw TypeError("Expected string");}return string.toUpperCase();
}async function consumer() {try {await toUppercase(98);} catch (error) {console.error(error.message);} finally {console.log("Finally");}
}consumer();

输出结果如下:

fileOf7174.png

6、异步生成器的错误处理

JavaScript 中的异步生成器是能够生成 Promise 而不是简单值的生成器函数。它将生成器函数与异步相结合,结果是一个生成器函数,其迭代器对象向消费者公开一个 Promise。

要创建一个异步生成器,需要声明一个带有星号 * 的生成器函数,前缀为 async:

async function* asyncGenerator() {yield 33;yield 99;throw Error("Bad!"); // Promise.reject
}

因为异步生成器是基于 Promise,所以同样适用 Promise 的错误处理规则,在异步生成器中,throw 会导致 Promise 拒绝,可以用 catch 拦截它。

要想从异步生成器处理 Promise,可以使用 then:

const go = asyncGenerator();go.next().then(value => console.log(value));
go.next().then(value => console.log(value));
go.next().catch(reason => console.error(reason.message));

输出结果如下:

fileOf7174.png

也使用异步迭代 for await...of。 要使用异步迭代,需要用 async 函数包装 consumer:

async function* asyncGenerator() {yield 33;yield 99;throw Error("Bad"); // Promise.reject
}async function consumer() {for await (const value of asyncGenerator()) {console.log(value);}
}consumer();

与 async/await 一样,可以使用 try/catch 来处理任何异常:

async function* asyncGenerator() {yield 33;yield 99;throw Error("Bad"); // Promise.reject
}async function consumer() {try {for await (const value of asyncGenerator()) {console.log(value);}} catch (error) {console.error(error.message);}
}consumer();

输出结果如下:

fileOf7174.png

从异步生成器函数返回的迭代器对象也有一个  throw()  方法。在这里对迭代器对象调用 throw() 不会抛出异常,而是 Promise 拒绝:

async function* asyncGenerator() {yield 33;yield 99;yield 11;
}const go = asyncGenerator();go.next().then(value => console.log(value));
go.next().then(value => console.log(value));go.throw(Error("Reject!"));go.next().then(value => console.log(value)); 

输出结果如下:

fileOf7174.png

可以通过以下方式来捕获错误:

go.throw(Error("Let's reject!")).catch(reason =>console.error(reason.message)
);

我们知道,迭代器对象的 throw() 是在生成器内部发送异常的。所以还可以使用以下方式来处理错误:

async function* asyncGenerator() {try {yield 33;yield 99;yield 11;} catch (error) {console.error(error.message);}
}const go = asyncGenerator();go.next().then(value => console.log(value));
go.next().then(value => console.log(value));go.throw(Error("Reject!"));go.next().then(value => console.log(value));

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com