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
55
56
57
58
59
60
61
62
63
64
|
/* eslint-env browser */
/**
* This fetch function is adapted from a `loadImage` function
* credited to Parziphal, Feb 13, 2017.
* https://stackoverflow.com/a/42196770
*
* The callback is generally run with the loading progress as a decimal 0-1.
* However, if it's not possible to compute the progress ration (which might
* only become apparent after a progress amount *has* been sent!),
* the callback will be run with the value -1.
*
* The return promise resolves to a manually instantiated Response object
* which generally behaves the same as a normal fetch response; access headers,
* text, blob, arrayBuffer as usual. Accordingly, non-200 responses do *not*
* reject the prmoise, so be sure to check the response status yourself.
*/
export function fetchWithProgress(url, progressCallback) {
return new Promise(resolve => {
const xhr = new XMLHttpRequest();
let notifiedNotComputable = false;
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onprogress = event => {
if (notifiedNotComputable) {
return;
}
if (!event.lengthComputable) {
notifiedNotComputable = true;
progressCallback(-1);
return;
}
progressCallback(event.loaded / event.total);
};
xhr.onloadend = () => {
const body = xhr.response;
const options = {
status: xhr.status,
headers:
parseResponseHeaders(xhr.getAllResponseHeaders()),
};
resolve(new Response(body, options));
};
xhr.send();
});
function parseResponseHeaders(headers) {
return (
Object.fromEntries(
headers
.trim()
.split(/[\r\n]+/)
.map(line => line.match(/(.+?):\s*(.+)/))
.map(match => [match[1], match[2]])));
}
}
|