@@ -84,6 +84,52 @@ const createFetchOptions = (url, options, type) => {
8484 return [ url , fetchOptions ] ;
8585} ;
8686
87+ /**
88+ * This is a fetch polyfill for XMLHttpRequest.
89+ * Mainly used to get upload progress indicator.
90+ */
91+ const fetchXhr = ( target , fetchOptions ) => new Promise ( ( resolve , reject ) => {
92+ const req = new XMLHttpRequest ( ) ;
93+ let onProgress = ( ) => { } ;
94+
95+ const onError = ( msg ) => ( ev ) => {
96+ console . warn ( msg , ev ) ;
97+ reject ( new Error ( msg ) ) ;
98+ } ;
99+
100+ const onLoad = ( ) => {
101+ resolve ( {
102+ status : req . status ,
103+ statusText : req . statusText ,
104+ ok : req . status >= 200 && req . status <= 299 ,
105+ headers : {
106+ get : k => req . getResponseHeader ( k )
107+ } ,
108+ text : ( ) => Promise . resolve ( JSON . responseText ) ,
109+ json : ( ) => Promise . resolve ( JSON . parse ( req . responseText ) ) ,
110+ arrayBuffer : ( ) => Promise . resolve ( req . response )
111+ } ) ;
112+ } ;
113+
114+ if ( typeof fetchOptions . onProgress === 'function' ) {
115+ onProgress = ( ev ) => {
116+ if ( ev . lengthComputable ) {
117+ const percentComplete = ev . loaded / ev . total * 100 ;
118+ fetchOptions . onProgress ( ev , percentComplete ) ;
119+ }
120+ } ;
121+ }
122+
123+ req . addEventListener ( 'load' , onLoad ) ;
124+ req . addEventListener ( 'error' , onError ( 'An error occured while performing XHR request' ) ) ;
125+ req . addEventListener ( 'abort' , onError ( 'XHR request was aborted' ) ) ;
126+ req . addEventListener ( 'progress' , onProgress ) ;
127+ req . open ( fetchOptions . method , target ) ;
128+ Object . entries ( fetchOptions . headers ) . forEach ( ( [ k , v ] ) => req . setRequestHeader ( k , v ) ) ;
129+ req . responseType = fetchOptions . responseType || '' ;
130+ req . send ( fetchOptions . body ) ;
131+ } ) ;
132+
87133/**
88134 * Make a HTTP request
89135 *
@@ -100,7 +146,11 @@ export const fetch = (url, options = {}, type = null) => {
100146 ? error
101147 : `${ response . status } (${ response . statusText } )` ) ) ;
102148
103- return window . fetch ( target , fetchOptions )
149+ const op = options . xhr
150+ ? fetchXhr ( target , fetchOptions )
151+ : window . fetch ( target , fetchOptions ) ;
152+
153+ return op
104154 . then ( response => {
105155 if ( ! response . ok ) {
106156 const contentType = response . headers . get ( 'content-type' ) ;
0 commit comments