Skip to content

Commit 517c088

Browse files
committed
Added XHR alternative for fetch
1 parent 31a597d commit 517c088

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

src/utils/fetch.js

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)