我的代码:给XHR添加hooks,在各个阶段打印日志

628 阅读1分钟
class XHR {
    constructor(beforeHooks = {}, afterHooks = {}) {
        //放两种钩子,一个是在之前调用,一个是在之后调用
        this.beforeHooks = beforeHooks;
        this.afterHooks = afterHooks
        this.xhr = window.XMLHttpRequest; //保存住原来的XHR
        this.init()
    }
    init() {
        let _this = this;
        window.XMLHttpRequest = function () {//用function是为了保留this
            this._xhr = new _this.xhr();
            _this.overwrite(this);//这个this指向new XMLHttpRequest的实例
        }
    }
    overwrite(newThis) {
        for (let proto in newThis._xhr) {
            //把原方法挂到实例化的方法上,使其可以正常调用
            if (typeof newThis._xhr[proto] === 'function') {//原型链的方法
                this.writeFunction(newThis, proto)
                continue
            }
            this.writeAttributes(newThis, proto)

        }
    }
    writeAttributes(newThis, proto) {
        Object.defineProperty(newThis, proto, this.setdefineProoerty(newThis, proto))
    }
    setdefineProoerty(newThis, proto) {
        let obj = Object.create(null);
        let _this = this;
        obj.set = function (val) {
            if (!proto.startsWith('on')) {
                newThis[`__${proto}`] = val;
                return
            }
            if(_this.beforeHooks[proto]){
                this._xhr[proto] = function(...arg){
                    _this.beforeHooks[proto].call(newThis)
                    val.apply(newThis,arg)
                }
                return
            }
            this._xhr[proto] = val
        }
        obj.get = function(){
            return newThis[`__${proto}`] || this._xhr[proto]
        }
        return obj
    }
    writeFunction(newThis, proto) {
        newThis[proto] = (...arg) => {
            if (this.beforeHooks[proto] && this.beforeHooks[proto]()) {
                return false
            }
            debugger
            newThis._xhr[proto].apply(newThis, arg);
            this.afterHooks[proto] && this.afterHooks[proto]()
        }
    }
}
new XHR({
    open: function () {
        console.log('open');
        // return true //阻塞进程
    },
    onload: function () {
        console.log('onload')
    },
    onreadystatechange: function () {
        console.log('onreadystatechange')
    },
    onerror: function () {
        console.log('onerror')
    }
})
let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.baidu.com', true);
xhr.send();
xhr.onreadystatechange = function (res) {
    consonle.log(res)
}