11export const cancelKey = "_ufs_cancel_" ;
22
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+ }
1113
1214 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 ?. ( ) ) ;
1816 } ;
1917}
2018
@@ -35,12 +33,12 @@ function initFetch() {
3533 window . fetch = async function ( url , options ) {
3634 let request = { url, options } ;
3735 for ( let { fn } of onBeforeFetchFn )
38- request = fn ( request . url , request . options ) || request ;
36+ request = fn ?. ( request . url , request . options ) || request ;
3937 if ( request ?. options ?. [ cancelKey ] ) return null ;
4038
4139 let response = await originalFetch ( ...request ) ;
4240 for ( let { fn } of onAfterFetchFn )
43- response = fn ( request . url , request . options , response ) || response ;
41+ response = fn ?. ( request . url , request . options , response ) || response ;
4442
4543 return response ;
4644 } ;
@@ -51,12 +49,10 @@ export function hookFetch({ onBefore, onAfter } = {}) {
5149 initFetch ( ) ;
5250 readyFetch = true ;
5351 }
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+ ] ) ;
6056}
6157
6258/* hookFetch example
@@ -67,61 +63,79 @@ hookFetch({
6763 },
6864 onAfter: (url, options, response) => {
6965 console.log(url, options, response);
70- return res;
66+ reponse = null; // modify response
67+ return response;
7168 },
7269});
7370*/
7471
7572// =========== XHR ============
76- const onBeforeXHRFn = [ ] ;
77- const onAfterXHRFn = [ ] ;
73+ const onBeforeOpenXHRFn = [ ] ;
74+ const onBeforeSendXHRFn = [ ] ;
75+ const onAfterSendXHRFn = [ ] ;
7876let readyXhr = false ;
7977
8078export const CANCEL_XHR = {
8179 [ cancelKey ] : true ,
8280} ;
8381
8482function 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+ } ) ;
103117}
104118
105- export function hookXHR ( { onBefore , onAfter } = { } ) {
119+ export function hookXHR ( { onBeforeOpen , onBeforeSend , onAfterSend } = { } ) {
106120 if ( ! readyXhr ) {
107121 initXhr ( ) ;
108- readyFetch = true ;
122+ readyXhr = true ;
109123 }
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+ ] ) ;
116129}
117130
118131/* hookXHR example
119132hookXHR({
120- onBefore : ({ method, url, async, user, password }) => {
133+ onBeforeOpen : ({method, url, async, user, password}) => {
121134 // return CANCEL_XHR;
122135 },
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 ;
125138 },
139+ onAfterSend: ({method, url, async, user, password}, dataSend, response) => {}
126140});
127141*/
0 commit comments