关于 JavaScript 错误处理的最完整指南(下半部)(1)

在这里,我们使用catch处理错误,输出如下:

AggregateError: No Promise in Promise.any was resolved

Always runs!

AggregateError对象具有与基本Error相同的属性,外加errors属性:

//

.catch(error => console.error(error.errors))

//

此属性是由reject产生的每个单独错误的数组

[Error: "No good, sorry!, Error: “Bad day …”]

使用 Promise.race 来处理错误


Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

const promise1 = Promise.resolve(“The first!”);

const promise2 = Promise.resolve(“The second!”);

Promise.race([promise1, promise2]).then(result => console.log(result));

// The first!

这里说明,第一个 Promise 比第二个行执行完。那包含拒绝的情况又是怎么样的?

const promise1 = Promise.resolve(“The first!”);

const rejection = Promise.reject(Error(“Ouch!”));

const promise2 = Promise.resolve(“The second!”);

Promise.race([promise1, rejection, promise2]).then(result =>

console.log(result)

);

// The first!

如果把reject放在第一个又会怎么样?

const promise1 = Promise.resolve(“The first!”);

const rejection = Promise.reject(Error(“Ouch!”));

const promise2 = Promise.resolve(“The second!”);

Promise.race([rejection, promise1, promise2])

.then(result => console.log(result))

.catch(error => console.error(error.message));

// Ouch!

使用 Promise.allSettled 来处理错误


Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilledrejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。

考虑下面示例:

const promise1 = Promise.resolve(“Good!”);

const promise2 = Promise.reject(Error(“No good, sorry!”));

Promise.allSettled([promise1, promise2])

.then(results => console.log(results))

.catch(error => console.error(error))

.finally(() => console.log(“Always runs!”));

我们传递给Promise.allSettled一个由两个Promise组成的数组:一个已解决,另一个被拒绝。

这种情况 catch 不会被执行, finally 永远会执行。

[

{ status: ‘fulfilled’, value: ‘Good!’ },

{

status: ‘rejected’,

reason: Error: No good, sorry!

}

]

使用 async/await 来处理错误


为了简单起见,我们使用前面的同步函数toUppercase,并通过在function关键字前放置async来将其转换为异步函数

async function toUppercase(string) {

if (typeof string !== “string”) {

throw TypeError(“Wrong type given, expected a string”);

}

return string.toUpperCase();

}

只要在函数前面加上async,该函数就会返回一个Promise。这意味着我们可以在函数调用之后进行thencatchfinally 操作

async function toUppercase(string) {

if (typeof string !== “string”) {

throw TypeError(“Wrong type given, expected a string”);

}

return string.toUpperCase();

}

toUppercase(“abc”)

.then(result => console.log(result))

.catch(error => console.error(error.message))

.finally(() => console.log(“Always runs!”));

当从 async 函数抛出异常时,我们就可以使用 catch 来捕获。

最重要的是,除了这种方式外,我们可以还使用try/catch/finally,就像我们使用同步函数所做的一样。

async function toUppercase(string) {

if (typeof string !== “string”) {

throw TypeError(“Wrong type given, expected a string”);

}

return string.toUpperCase();

}

async function consumer() {

try {

await toUppercase(98);

} catch (error) {

console.error(error.message);

} finally {

console.log(“Always runs!”);

}

}

consumer();

输出:

Wrong type given, expected a string

Always runs!

使用 async generators 来处理错误


JavaScript中的async generators是能够生成 Promises 而不是简单值的生成器函数。

async function* asyncGenerator() {

yield 33;

yield 99;

throw Error(“Something went wrong!”); // Promise.reject

}

基于 Promise,此处适用于错误处理的相同规则。 在异步生成器中 throw 将会触发 Promise 的reject,我们可以使用catch对其进行拦截。

为了使用异步生成器的 Promise,我们可以这样做:

  • then 方法

  • 异步遍历

从上面我们知道,在两次调用 yield之后,下一次会抛出一个异常:

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

输出结果:

{ value: 33, done: false }

{ value: 99, done: false }

Something went wrong!

别一种是使用 异步遍历for await...of:

async function* asyncGenerator() {

yield 33;

yield 99;

throw Error(“Something went wrong!”); // 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(“Something went wrong!”); // Promise.reject

}

async function consumer() {

try {

for await (const value of asyncGenerator()) {

console.log(value);

}

} catch (error) {

console.error(error.message);

}

}

consumer();

输出结果:

33

99

Something went wrong!

从异步生成器函数返回的迭代器对象也具有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(“Let’s reject!”));

go.next().then(value => console.log(value)); // value is undefined

要从外部处理这种情况,我们可以做:

go.throw(Error(“Let’s reject!”)).catch(reason => console.error(reason.message));

Node 中的错误处理


Node 中的同步错误处理

Node.js 中的同步错误处理与到目前为止所看到的并没有太大差异。对于同步,使用 try/catch/finally 就可以很好的工作了。

Node.js 中的异步错误处理:回调模式

对于异步代码,Node.js 主要使用这两种方式:

  • 回调模式

  • event emitters

在回调模式中,异步 Node.js API 接受一个函数,该函数通过事件循环处理,并在调用堆栈为空时立即执行。

考虑以下代码:

const { readFile } = require(“fs”);

function readDataset(path) {

readFile(path, { encoding: “utf8” }, function(error, data) {

if (error) console.error(error);

// do stuff with the data

});

}

我们可以看到,这里处理错误的方式是使用了回调:

//

function(error, data) {

if (error) console.error(error);

// do stuff with the data

}

//

如果使用fs.readFile读取给定路径而引起任何错误,我们将获得一个错误对象。

在这一点上,我们可以:

  • 简单的把对象错误打出来

  • 抛出错误

  • 把错误传到另一个回调

我们可以抛出一个异常

const { readFile } = require(“fs”);

function readDataset(path) {

readFile(path, { encoding: “utf8” }, function(error, data) {

if (error) throw Error(error.message);

// do stuff with the data

});

}

但是,与 DOM 中的事件和定时器一样,此异常将使程序崩溃。 通过try/catch捕获它是不起作用的:

const { readFile } = require(“fs”);

function readDataset(path) {

readFile(path, { encoding: “utf8” }, function(error, data) {

if (error) throw Error(error.message);

// do stuff with the data

});

}

try {

readDataset(“not-here.txt”);

} catch (error) {

console.error(error.message);

}

如果我们不想使程序崩溃,则将错误传递给另一个回调是首选方法:

const { readFile } = require(“fs”);

function readDataset(path) {

readFile(path, { encoding: “utf8” }, function(error, data) {

if (error) return errorHandler(error);

// do stuff with the data

});

}

这里的errorHandler顾名思义,是一个用于错误处理的简单函数:

function errorHandler(error) {

console.error(error.message);

// do something with the error:

// - write to a log.

// - send to an external logger.

}

Node.js 中的异步错误处理:event emitters


在 Node.js 中所做的大部分工作都是基于事件的。 大多数情况下,emitter object 和一些观察者进行交互以侦听消息。

Node.js中的任何事件驱动模块(例如net)都扩展了一个名为EventEmitter的根类。

Node.js中的EventEmitter有两种基本方法:onemit

考虑以下简单的 HTTP 服务器:

const net = require(“net”);

const server = net.createServer().listen(8081, “127.0.0.1”);

server.on(“listening”, function () {

console.log(“Server listening!”);

});

server.on(“connection”, function (socket) {

console.log(“Client connected!”);

socket.end(“Hello client!”);

});

这里我们来听两个事件:listeningconnection。除了这些事件之外,event emitters 还公开一个 error 事件,以防发生错误。

如果在端口80上运行这段代码,而不是在前面的示例上侦听,将会得到一个异常:

const net = require(“net”);

const server = net.createServer().listen(80, “127.0.0.1”);

server.on(“listening”, function () {

console.log(“Server listening!”);

});

server.on(“connection”, function (socket) {

console.log(“Client connected!”);

socket.end(“Hello client!”);

});

输出:

events.js:291

throw er; // Unhandled ‘error’ event

^

Error: listen EACCES: permission denied 127.0.0.1:80

Emitted ‘error’ event on Server instance at: …

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
ction (socket) {

console.log(“Client connected!”);

socket.end(“Hello client!”);

});

输出:

events.js:291

throw er; // Unhandled ‘error’ event

^

Error: listen EACCES: permission denied 127.0.0.1:80

Emitted ‘error’ event on Server instance at: …

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-LxpstZVK-1715085752889)]

[外链图片转存中…(img-J0GRuneL-1715085752889)]

[外链图片转存中…(img-p0qH9z37-1715085752889)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值