Promissify
# 前言
注意一下:源码这里有个小坑要注意一下,就是源码目录不能有中文路径,不然会报错。
# promisify
函数是把 callback
形式转成 promise
形式
# promisify方法的实现
其中:
Reflect.apply(original, this, args)
使用apply或者Reflect.apply
的目的是为了保存this对象。- promisify函数主要针对了采用遵循常见的错误优先的回调风格的函数(也就是将
(err, value) => ...
回调作为最后一个参数),并返回一个返回 promise 的版本。 - 其中通过
reject
返回函数中的错误reject(err)
,使用的resolve()
返回回调函数。这样就可以通过promise.catch()
来捕捉函数中的错误异常,并且通过promise.then()
或者await
等方法获取回调函数进行链式调用。
function promisify(original) {
function fn(...args) {
return new Promise((resolve, reject) => {
args.push((err, ...values) => {
if (err) {
return reject(err);
}
resolve(values);
});
// original.apply(this, args);
Reflect.apply(original, this, args);
// original(...args)
});
}
return fn;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用Reflect.apply(original, this, args);
的原因
保存this的对象,防止丢失。也可使用apply等方法将函数中的this保存下来。如果不使用此方法,会造成promise化中函数的this丢失。
例如:
class Foo {
constructor() {
this.a = 42;
}
bar(callback) {
callback(null, this.a);
console.log('bar', this)
}
}
const foo = new Foo();
foo.bar(()=>{})// 1
const naiveBar = promisify(foo.bar);
naiveBar().then(a => {}) // 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上面代码中,如果没有使用apply
等方法去对this进行一个保存。1
中会正常输出Foo
类中的属性a = 42;但是2
中会爆出如下错误:
通过代码调试的方法可以看到,第一次调用没有promisify化的函数bar的时候this是正常的指向类的
而再次向下进行时,此时的bar函数已经被promisify化了。此时promisify函数没有做出this的保存,只是对函数参数进行了简单的结构传参:
则this丢失,变成了undefined,所以报错了。
而对函数的this
对象进行一次this
的传入,函数中会丢失类中的this
,而this指向了promisify函数通过apply
方法传入的this
,在这里是window
对象,所以这里也证明了==this总是在运行中获取确认指向的,而不是在一开始就定了的==
# 总结
本次源码阅读中,除了跟着川哥学习了promisify函数的实现以及应用场景,还对函数中Reflect.apply(original, this, args)
进行了一次深入的了解,从而学到了一部分this的运行方法以及指向的问题。
上两周被大作业折磨的没空写下笔记,如今终于空了下来对这次的笔记进行了梳理和解析。希望能够对未来看到这篇笔记的朋友们有所帮助。
谢谢川哥,谢谢各位帮助过
编辑 (opens new window)
上次更新: 2022/02/21, 05:57:00