simker

Life is too short, just make it.


  • 首页

  • 归档

  • 分类

  • 标签

  • 关于

  • 音乐

  • 搜索

记一次关于extends的bug

发表于 2021-09-29 阅读次数: Disqus:
本文字数: 2.2k 阅读时长 ≈ 2 分钟

Your browser does not support the audio tag.

记录一次关于用typescript封装restful api碰到的问题

这是我在 learn_koa 里面遇到的一个问题.

场景复现:

我需要封装Error到一个基类上面,然后后续所有自定义的异常全部继承这个基类,以后处理业务的时候就可以争对性处理。以下是js 的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class BaseError extends Error {
errorCode = 0

construct(errorCode = 0) {
super()
if (errorCode) {
this.errorCode = errorCode;
}
}
}

class CustomError extends BaseError {
errorCode = 100001

construct(errorCode = 0) {
super()
if (errorCode) {
this.errorCode = errorCode;
}
}
}

function start () {
try {
const success = Math.random() > 0.5;
if (success) {
throw new CustomError();
} else {
throw new Error();
}
} catch (e) {
if (e instanceof BaseError) {
// 出现了一个已知的错误
console.log('出错了!')
} else {
// 出现一个未知的错误
console.log('出错了!!!!')
// 通知维护人员,处理业务出现未知错误
}
}
}

start();

如上,我用了一个随机数来模拟处理业务出错的情况,在碰到已知的错误时我们可以用已有的逻辑来处理,比如参数校验错误了,直接通知前端错误,请求第三方出错了,就通知系统的维护人员。本质上的核心代码就是这一句:

1
(new CustomError()) instanceof BaseError; // true

在这里面的示例是可以返回true的,但是我在迁移到ts的时候。发现:

1
(new CustomError()) instanceof BaseError; // false

你没有看错,是false,当然这只在tsconfig 设置 compilerOptions 打包至es5的情况下,es6不存在以上的问题,但是目前大部分项目还是要降级到es5。

那么,这是为什么呢?我们可以通过两个原型链来看看。

1
console.log((new CustomError()).__proto__) // Error {}

如此,我们可以清楚的看到我们自定义的对象实例的本质是Error对象,并不是BaseError, 所以我们使用instanceof的时候是false。

那,有什么办法可以改变实例后的原型链么?

其实TS官方已经给出了答案,只需要在构造函数下加入下面一句就可以了

1
Object.setPrototypeOf(this, new.target.prototype);

完整实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

class BaseError extends Error {
errorCode: number = 0

construct(errorCode: number = 0) {
super()
Object.setPrototypeOf(this, new.target.prototype);
if (errorCode) {
this.errorCode = errorCode;
}
}
}

class CustomError extends BaseError {
errorCode: number = 100001

construct(errorCode: number = 0) {
super()
if (errorCode) {
this.errorCode = errorCode;
}
}
}

function start () {
try {
const success = Math.random() > 0.5;
if (success) {
throw new CustomError();
} else {
throw new Error();
}
} catch (e) {
if (e instanceof BaseError) {
// 出现了一个已知的错误
console.log('出错了!')
} else {
// 出现一个未知的错误
console.log('出错了!!!!')
// 通知维护人员,处理业务出现未知错误
}
}
}

start();

我曾经被这个问题困扰了很久,于是把这个记录下来,以方便后续查看。

Cai xian 微信支付

微信支付

Cai xian 支付宝

支付宝

# typescript
前端面试题整理之JS篇
如何用css隐藏scrollbar
Cai xian

Cai xian

A super nice guy!
24 日志
12 分类
15 标签
© 2019 – 2021 Cai xian | 70k | 1:04
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Pisces v7.3.0
|