1
1
export const cancelKey = "_ufs_cancel_" ;
2
2
3
- function hook ( { onBefore, onAfter, onBeforeArr, onAfterArr } = { } ) {
4
- const beforeId = randId ( ) ;
5
- const afterId = randId ( ) ;
6
-
7
- if ( typeof onBefore === "function" )
8
- onBeforeArr . push ( { fn : onBefore , id : beforeId } ) ;
9
- if ( typeof onAfter === "function" )
10
- onAfterArr . push ( { fn : onAfter , id : afterId } ) ;
3
+ function _hook ( configs = [ ] ) {
4
+ const unsubFn = [ ] ;
5
+ for ( let { fn, arr } of configs ) {
6
+ let id = randId ( ) ;
7
+ arr . push ( { fn, id } ) ;
8
+ unsubFn . push ( ( ) => {
9
+ let index = arr . findIndex ( ( e ) => e . id === id ) ;
10
+ if ( index !== - 1 ) arr . splice ( index , 1 ) ;
11
+ } ) ;
12
+ }
11
13
12
14
return ( ) => {
13
- let beforeIndex = onBeforeArr . findIndex ( ( e ) => e . id === beforeId ) ;
14
- let afterIndex = onAfterArr . findIndex ( ( e ) => e . id === afterId ) ;
15
-
16
- if ( beforeIndex !== - 1 ) onBeforeArr . splice ( beforeIndex , 1 ) ;
17
- if ( afterIndex !== - 1 ) onAfterArr . splice ( afterIndex , 1 ) ;
15
+ unsubFn . forEach ( ( fn ) => fn ?. ( ) ) ;
18
16
} ;
19
17
}
20
18
@@ -35,12 +33,12 @@ function initFetch() {
35
33
window . fetch = async function ( url , options ) {
36
34
let request = { url, options } ;
37
35
for ( let { fn } of onBeforeFetchFn )
38
- request = fn ( request . url , request . options ) || request ;
36
+ request = fn ?. ( request . url , request . options ) || request ;
39
37
if ( request ?. options ?. [ cancelKey ] ) return null ;
40
38
41
39
let response = await originalFetch ( ...request ) ;
42
40
for ( let { fn } of onAfterFetchFn )
43
- response = fn ( request . url , request . options , response ) || response ;
41
+ response = fn ?. ( request . url , request . options , response ) || response ;
44
42
45
43
return response ;
46
44
} ;
@@ -51,12 +49,10 @@ export function hookFetch({ onBefore, onAfter } = {}) {
51
49
initFetch ( ) ;
52
50
readyFetch = true ;
53
51
}
54
- return hook ( {
55
- onBefore,
56
- onAfter,
57
- onBeforeArr : onBeforeFetchFn ,
58
- onAfterArr : onAfterFetchFn ,
59
- } ) ;
52
+ return _hook ( [
53
+ { fn : onBefore , arr : onBeforeFetchFn } ,
54
+ { fn : onAfter , arr : onAfterFetchFn } ,
55
+ ] ) ;
60
56
}
61
57
62
58
/* hookFetch example
@@ -67,61 +63,79 @@ hookFetch({
67
63
},
68
64
onAfter: (url, options, response) => {
69
65
console.log(url, options, response);
70
- return res;
66
+ reponse = null; // modify response
67
+ return response;
71
68
},
72
69
});
73
70
*/
74
71
75
72
// =========== XHR ============
76
- const onBeforeXHRFn = [ ] ;
77
- const onAfterXHRFn = [ ] ;
73
+ const onBeforeOpenXHRFn = [ ] ;
74
+ const onBeforeSendXHRFn = [ ] ;
75
+ const onAfterSendXHRFn = [ ] ;
78
76
let readyXhr = false ;
79
77
80
78
export const CANCEL_XHR = {
81
79
[ cancelKey ] : true ,
82
80
} ;
83
81
84
82
function initXhr ( ) {
85
- let oldXHROpen = window . XMLHttpRequest . prototype . open ;
86
- window . XMLHttpRequest . prototype . open = function (
87
- method ,
88
- url ,
89
- async ,
90
- user ,
91
- password
92
- ) {
93
- let params = { method, url, async, user, password } ;
94
- for ( let { fn } of onBeforeXHRFn ) params = fn ( params ) || params ;
95
- if ( params ?. [ cancelKey ] ) return ;
96
-
97
- this . addEventListener ( "load" , function ( ) {
98
- for ( let { fn } of onAfterXHRFn ) fn ( params , this . responseText ) ;
99
- } ) ;
100
-
101
- return oldXHROpen . apply ( this , Object . values ( params ) ) ;
102
- } ;
83
+ const orig = window . XMLHttpRequest ;
84
+ window . XMLHttpRequest = new Proxy ( orig , {
85
+ construct ( o , r ) {
86
+ const instance = new o ( ...r ) ;
87
+
88
+ let p ;
89
+
90
+ const open = instance . open ;
91
+ instance . open = function ( method , url , async , user , password ) {
92
+ this . _method = method ;
93
+ this . _url = url ;
94
+
95
+ p = { method, url, async, user, password } ;
96
+ for ( let { fn } of onBeforeOpenXHRFn ) p = fn ?. ( p ) || p ;
97
+ if ( p ?. [ cancelKey ] ) return ;
98
+
99
+ return open . apply ( this , [ p . mr ] ) ;
100
+ } ;
101
+
102
+ const send = instance . send ;
103
+ instance . send = function ( data ) {
104
+ for ( let { fn } of onBeforeSendXHRFn ) data = fn ?. ( p , data ) || data ;
105
+ if ( data ?. [ cancelKey ] ) return ;
106
+
107
+ instance . addEventListener ( "load" , function ( ) {
108
+ for ( let { fn } of onAfterSendXHRFn )
109
+ fn ?. ( p , data , instance . responseText ) ;
110
+ } ) ;
111
+
112
+ return send . apply ( this , arguments ) ;
113
+ } ;
114
+ return instance ;
115
+ } ,
116
+ } ) ;
103
117
}
104
118
105
- export function hookXHR ( { onBefore , onAfter } = { } ) {
119
+ export function hookXHR ( { onBeforeOpen , onBeforeSend , onAfterSend } = { } ) {
106
120
if ( ! readyXhr ) {
107
121
initXhr ( ) ;
108
- readyFetch = true ;
122
+ readyXhr = true ;
109
123
}
110
- return hook ( {
111
- onBefore,
112
- onAfter,
113
- onBeforeArr : onBeforeXHRFn ,
114
- onAfterArr : onAfterXHRFn ,
115
- } ) ;
124
+ return _hook ( [
125
+ { fn : onBeforeOpen , arr : onBeforeOpenXHRFn } ,
126
+ { fn : onBeforeSend , arr : onBeforeSendXHRFn } ,
127
+ { fn : onAfterSend , arr : onAfterSendXHRFn } ,
128
+ ] ) ;
116
129
}
117
130
118
131
/* hookXHR example
119
132
hookXHR({
120
- onBefore : ({ method, url, async, user, password }) => {
133
+ onBeforeOpen : ({method, url, async, user, password}) => {
121
134
// return CANCEL_XHR;
122
135
},
123
- onAfter : ({ method, url, async, user, password }, responseText ) => {
124
- console.log({ url, method, dataSend, response }) ;
136
+ onBeforeSend : ({method, url, async, user, password}, dataSend ) => {
137
+ // return CANCEL_XHR ;
125
138
},
139
+ onAfterSend: ({method, url, async, user, password}, dataSend, response) => {}
126
140
});
127
141
*/
0 commit comments