-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmultiple-promises.html
108 lines (96 loc) · 3.09 KB
/
multiple-promises.html
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<!DOCTYPE html>
<html lang="en">
<head>
<title>Correctly set aria-busy when dealing with multiple promises</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description"
content="aria-busy should only be removed when all requests have resolved">
<link href="joy.css" rel="stylesheet">
</head>
<body>
<a href="./index.html">List of all Examples</a>
<h1>Correctly set <code>aria-busy</code> when dealing with multiple promises</h1>
<p>
This is a small POC to test how setting <code>aria-busy</code> correctly
can work when we are retrieving multiple requests that will all modify
the current DOM of the component in question until the point in time
where all requests have been resolved. Only at this stage should we
remove the <code>aria-busy</code> attribute.
</p>
<p>
This also tests what happens when the execution of the requests overlap
with another series of requests. If another series of requests has
started, the <code>aria-busy</code> attribute should not be removed
until <em>those</em> requests have been resolved, even if the first
batch of requests has already been resolved.
</p>
<p>
This button initates two series of requests at the same time to simulate
the overlapping asynchronous behavior and to test that the aria-busy
attribute is correctly set.
</p>
<my-element>
<button>
Perform Requests
</button>
<ol></ol>
</my-element>
<script>
class MyElement extends HTMLElement {
connectedCallback() {
this.button.addEventListener("click", () => {
// Performs the requests multiple times to simulate
// overlapping asynchronous behavior.
this.performRequests();
this.performRequests();
});
}
performRequests() {
if (this.abort) {
this.abort();
}
this.setAttribute("aria-busy", "true");
this.appendToList("Starting retrieval... (aria-busy=true)");
let aborted = false;
this.abort = () => {
aborted = true;
};
let requests = this.urls.map(url => fetch(url).then(response => {
if (!aborted) {
this.appendToList(`${url} Status: ${response.status}`);
} else {
this.appendToList(`Requests aborted, ignoring ${response.status} from ${url}`);
}
return response.text();
}));
Promise.allSettled(requests).then(() => {
if (!aborted) {
this.appendToList("Finished! (aria-busy=false)");
this.removeAttribute("aria-busy");
} else {
this.appendToList("Requests aborted, aria-busy unchanged");
}
});
}
appendToList(text) {
let ol = this.querySelector("ol");
let li = document.createElement("li");
li.appendChild(document.createTextNode(text));
ol.appendChild(li);
}
get urls() {
return [
"./list-of-articles.html",
"./multiselect-dialog.html",
"./represent-labelled-information.html"
]
}
get button() {
return this.querySelector("button");
}
}
customElements.define("my-element", MyElement);
</script>
</body>
</html>