ajax-hooks

方法一:new实例

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
46
47
48
49
50
51
52

class AnyXHR {
constructor (beforeHooks = {}, afterHooks = {}) {
this.XHR = window.XMLHttpRequest
this.beforeHooks = beforeHooks
this.afterHooks = afterHooks
this.init()
}
init () {
let _this = this
window.XMLHttpRequest = function () {
this._xhr = new _this.XHR()
_this.overWrite(this)
}
}
overWrite (proxyXHR) {
for (let key in proxyXHR._xhr) {
if (typeof proxyXHR._xhr[key] === 'function') {
this.overwriteMethod(key, proxyXHR)
continue
}
}
}
overwriteMethod (key, proxyXHR) {
let beforeHooks = this.beforeHooks
let afterHooks = this.afterHooks
proxyXHR[key] = (...args) => {
// 前置钩子 可拦截
if (beforeHooks[key] && (beforeHooks[key].call(proxyXHR._xhr, args) === false)) return
// 执行原生方法
const res = proxyXHR._xhr[key].apply(proxyXHR._xhr, args)
// 后置钩子
afterHooks[key] && afterHooks[key].call(proxyXHR._xhr, res)
return res
}
}
}


new AnyXHR({
open: function (args) {
console.log('前置钩子执行')
console.log('open', args)
},
onreadystatechange: function (args) {
console.log('onreadystatechange', args)
}
}, {
open: function () {
console.log('后置钩子执行')
}
})

方法二:劫持原型

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
46
47
48
49
50
51
52
53
54
const ajaxHooks = {
init: function (hooks) {
let {
open = null,
send = null
} = hooks;
if (typeof window === 'undefined') return;

const _openPrototype = window.XMLHttpRequest.prototype.open;
const _sendPrototype = window.XMLHttpRequest.prototype.send;

const openReplacement = function(openHook, openPrototype) {
return function (method, url, async, user, password) {
openHook.apply(this, arguments)
return openPrototype.apply(this, arguments)
}
}

const getHookByProps = props => {
return function () {
hooks[props] && hooks[props].apply(this, arguments)
this[`_${props}`] && this[`_${props}`].apply(this, arguments);
}
}

const sendReplacement = function(sendHook, sendPrototype) {
return function () {
const onMappingKeyList = [
onreadystatechange,
onloadstart,
onloadend,
onerror,
ontimeout,
onabort
]

onMappingKeyList.forEach(key => {
this['_' + key] = this[key] ? this[key] : null;
this[key] = getHookByProps(key)
})

sendHook.apply(this, arguments)
return sendPrototype.apply(this, arguments)
}
}

window.XMLHttpRequest.prototype.open = openReplacement(open, _openPrototype)
window.XMLHttpRequest.prototype.send = sendReplacement(send, _sendPrototype)
}
}

export default ajaxHooks