Skip to content

Commit f330811

Browse files
authored
fix(decorators): Gracefully Handle File Read Errors (#53)
Used so files with read errors don't halt execution, instead are handled gracefully and submitted to the server
1 parent 7051ea0 commit f330811

3 files changed

Lines changed: 81 additions & 42 deletions

File tree

js-lib/src/decorators.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,36 @@ export const fileHandler = {
88
if (value === null || value === undefined) return value;
99
if (value.constructor && value.constructor === File) {
1010
const { name, lastModified, size, type } = value;
11-
const arrayBuffer = await new Promise((resolve) => {
12-
const reader = new FileReader();
13-
reader.addEventListener("loadend", () => {
14-
resolve(reader.result);
11+
12+
// Will be null in the event of an error on read, DataView otherwise
13+
let content = null;
14+
// Will be an error string if content failed to read, null otherwise
15+
let error = null;
16+
17+
try {
18+
const arrayBuffer = await new Promise((resolve, reject) => {
19+
const reader = new FileReader();
20+
reader.addEventListener("loadend", () => {
21+
resolve(reader.result);
22+
});
23+
reader.addEventListener("error", () => {
24+
reject(reader.error);
25+
});
26+
reader.readAsArrayBuffer(value);
1527
});
16-
reader.readAsArrayBuffer(value);
17-
});
18-
const content = new DataView(arrayBuffer);
28+
29+
content = new DataView(arrayBuffer);
30+
} catch (e) {
31+
error = e?.message ?? String(e);
32+
}
33+
1934
return {
2035
name,
2136
lastModified,
2237
size,
2338
type,
2439
content,
40+
error,
2541
// used by server to prevent sending those fields back to JS
2642
_filter: ["content"],
2743
};
@@ -38,13 +54,10 @@ export const fileListHandler = {
3854
return value;
3955
}
4056
if ((value.constructor && value.constructor === FileList) || value.length) {
41-
const results = [];
42-
/* eslint-disable no-await-in-loop */
43-
for (let i = 0; i < value.length; i++) {
44-
results.push(await fileHandler.decorate(value[i]));
45-
}
46-
/* eslint-enable no-await-in-loop */
47-
return results;
57+
const results = await Promise.allSettled(
58+
Array.from(value).map((file) => fileHandler.decorate(file)),
59+
);
60+
return results.map((result) => result.value);
4861
}
4962
return value;
5063
},

vue2-app/src/components/Connect/trame/decorators.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,36 @@ export const fileHandler = {
1414
if (value === null || value === undefined) return value;
1515
if (value.constructor && value.constructor === File) {
1616
const { name, lastModified, size, type } = value;
17-
const arrayBuffer = await new Promise((resolve) => {
18-
const reader = new FileReader();
19-
reader.addEventListener('loadend', () => {
20-
resolve(reader.result);
17+
18+
// Will be null in the event of an error on read, DataView otherwise
19+
let content = null;
20+
// Will be an error string if content failed to read, null otherwise
21+
let error = null;
22+
23+
try {
24+
const arrayBuffer = await new Promise((resolve, reject) => {
25+
const reader = new FileReader();
26+
reader.addEventListener('loadend', () => {
27+
resolve(reader.result);
28+
});
29+
reader.addEventListener('error', () => {
30+
reject(reader.error);
31+
});
32+
reader.readAsArrayBuffer(value);
2133
});
22-
reader.readAsArrayBuffer(value);
23-
});
24-
const content = new DataView(arrayBuffer);
34+
35+
content = new DataView(arrayBuffer);
36+
} catch (e) {
37+
error = e?.message ?? String(e);
38+
}
39+
2540
return {
2641
name,
2742
lastModified,
2843
size,
2944
type,
3045
content,
46+
error,
3147
// used by server to prevent sending those fields back to JS
3248
_filter: ['content'],
3349
};
@@ -44,13 +60,10 @@ export const fileListHandler = {
4460
return value;
4561
}
4662
if ((value.constructor && value.constructor === FileList) || value.length) {
47-
const results = [];
48-
/* eslint-disable no-await-in-loop */
49-
for (let i = 0; i < value.length; i++) {
50-
results.push(await fileHandler.decorate(value[i]));
51-
}
52-
/* eslint-enable no-await-in-loop */
53-
return results;
63+
const results = await Promise.allSettled(
64+
Array.from(value).map((file) => fileHandler.decorate(file))
65+
);
66+
return results.map((result) => result.value);
5467
}
5568
return value;
5669
},

vue3-app/src/core/trame/decorators.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,36 @@ export const fileHandler = {
1414
if (value === null || value === undefined) return value;
1515
if (value.constructor && value.constructor === File) {
1616
const { name, lastModified, size, type } = value;
17-
const arrayBuffer = await new Promise((resolve) => {
18-
const reader = new FileReader();
19-
reader.addEventListener("loadend", () => {
20-
resolve(reader.result);
17+
18+
// Will be null in the event of an error on read, DataView otherwise
19+
let content = null;
20+
// Will be an error string if content failed to read, null otherwise
21+
let error = null;
22+
23+
try {
24+
const arrayBuffer = await new Promise((resolve, reject) => {
25+
const reader = new FileReader();
26+
reader.addEventListener("loadend", () => {
27+
resolve(reader.result);
28+
});
29+
reader.addEventListener("error", () => {
30+
reject(reader.error);
31+
});
32+
reader.readAsArrayBuffer(value);
2133
});
22-
reader.readAsArrayBuffer(value);
23-
});
24-
const content = new DataView(arrayBuffer);
34+
35+
content = new DataView(arrayBuffer);
36+
} catch (e) {
37+
error = e?.message ?? String(e);
38+
}
39+
2540
return {
2641
name,
2742
lastModified,
2843
size,
2944
type,
3045
content,
46+
error,
3147
// used by server to prevent sending those fields back to JS
3248
_filter: ["content"],
3349
};
@@ -44,13 +60,10 @@ export const fileListHandler = {
4460
return value;
4561
}
4662
if ((value.constructor && value.constructor === FileList) || value.length) {
47-
const results = [];
48-
/* eslint-disable no-await-in-loop */
49-
for (let i = 0; i < value.length; i++) {
50-
results.push(await fileHandler.decorate(value[i]));
51-
}
52-
/* eslint-enable no-await-in-loop */
53-
return results;
63+
const results = await Promise.allSettled(
64+
Array.from(value).map((file) => fileHandler.decorate(file))
65+
);
66+
return results.map((result) => result.value);
5467
}
5568
return value;
5669
},

0 commit comments

Comments
 (0)