-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathclient.js
More file actions
87 lines (71 loc) · 2.06 KB
/
client.js
File metadata and controls
87 lines (71 loc) · 2.06 KB
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
export default function http(rootUrl) {
let loading = false;
let chunks = [];
let results = null;
let error = null;
let controller = null;
const json = async (path, options,) => {
_resetLocals();
let signal = controller.signal;
loading = true
try {
const response = await fetch(rootUrl + path, { signal, ...options });
if (response.status >= 200 && response.status < 300) {
results = await _readBody(response)
return JSON.parse(results)
} else {
throw new Error(response.statusText)
}
} catch (err) {
error = err
results = null
return error
} finally {
loading = false
}
}
const _readBody = async (response) => {
const reader = response.body.getReader();
const length = +response.headers.get('content-length');
let received = 0;
// Loop through the response stream and extract data chunks
while (loading) {
const { done, value } = await reader.read();
const payload = { detail: { received, length, loading } }
const onProgress = new CustomEvent('fetch-progress', payload);
const onFinished = new CustomEvent('fetch-finished', payload)
if (done) {
// Finish loading
loading = false;
window.dispatchEvent(onFinished)
} else {
// Push values to the chunk array
chunks.push(value);
received += value.length;
window.dispatchEvent(onProgress)
}
}
// Concat the chinks into a single array
let body = new Uint8Array(received);
let position = 0;
// Order the chunks by their respective position
for (let chunk of chunks) {
body.set(chunk, position);
position += chunk.length;
}
// Decode the response and return it
return new TextDecoder('utf-8').decode(body);
}
const _resetLocals = () => {
loading = false;
chunks = [];
results = null;
error = null;
controller = new AbortController();
}
const cancel = () => {
_resetLocals();
controller.abort();
};
return { json, cancel }
}