小曹同学的百草园
首页
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

小曹同学

一个普通的前端开发
首页
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Promissify

    • 前言
      • promisify方法的实现
        • 总结
        • 源码学习笔记
        小曹同学
        2021-12-06
        目录

        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

        # 使用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

        上面代码中,如果没有使用apply等方法去对this进行一个保存。1中会正常输出Foo类中的属性a = 42;但是2中会爆出如下错误:

        image-20211218141926532

        通过代码调试的方法可以看到,第一次调用没有promisify化的函数bar的时候this是正常的指向类的

        image-20211218142017779

        而再次向下进行时,此时的bar函数已经被promisify化了。此时promisify函数没有做出this的保存,只是对函数参数进行了简单的结构传参:

        image-20211218142155939

        则this丢失,变成了undefined,所以报错了。

        image-20211218142145460

        而对函数的this对象进行一次this的传入,函数中会丢失类中的this,而this指向了promisify函数通过apply方法传入的this,在这里是window对象,所以这里也证明了==this总是在运行中获取确认指向的,而不是在一开始就定了的==

        image-20211218142403663

        image-20211218142422917

        # 总结

        本次源码阅读中,除了跟着川哥学习了promisify函数的实现以及应用场景,还对函数中Reflect.apply(original, this, args)进行了一次深入的了解,从而学到了一部分this的运行方法以及指向的问题。

        上两周被大作业折磨的没空写下笔记,如今终于空了下来对这次的笔记进行了梳理和解析。希望能够对未来看到这篇笔记的朋友们有所帮助。

        谢谢川哥,谢谢各位帮助过

        编辑 (opens new window)
        上次更新: 2022/02/21, 05:57:00
        最近更新
        01
        优雅代码书写之道
        06-07
        02
        图片懒加载
        05-05
        03
        项目部署
        04-16
        更多文章>
        Theme by Vdoing
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式