Skip to content

Commit 73afdfc

Browse files
doc: use a chained Promise to serialize CodeMirror changes
This avoids an arbitrary setTimeout and reduces the amount of state. Discussed in review comments on #1255
1 parent d972dcc commit 73afdfc

File tree

1 file changed

+63
-68
lines changed

1 file changed

+63
-68
lines changed

doc/js/demo.js

Lines changed: 63 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -123,84 +123,79 @@ function aux_demo(input_id, input_files, main_file, output_id, process_func) {
123123

124124
for (let textarea_id in editor_by_textarea_id) {
125125
let editor = editor_by_textarea_id[textarea_id];
126-
let startedJobId = 0;
127-
let finishedJobId = 0;
128-
editor.on('change', async function() {
129-
// Yield until we finish duplicated change events (#1254)
130-
startedJobId += 1;
131-
const currJobId = startedJobId;
132-
while (finishedJobId < currJobId - 1) {
133-
await new Promise(resolve => setTimeout(resolve, 10));
134-
}
135-
136-
try {
137-
// Clean out the existing textareas and tabs.
138-
// There should be only one.
139-
let tab_header = output.getElementsByClassName('tab-header')[0];
140-
let last_selected;
141-
while (tab_header.firstChild) {
142-
let child = tab_header.firstChild;
143-
if (child.className == 'selected') {
144-
last_selected = child.innerHTML;
126+
// Serialize processing of change events, otherwise they can interfere with each other.
127+
let ongoingChange = Promise.resolve(true);
128+
editor.on('change', () => {
129+
return (ongoingChange = ongoingChange.then(async () => {
130+
try {
131+
// Clean out the existing textareas and tabs.
132+
// There should be only one.
133+
let tab_header = output.getElementsByClassName('tab-header')[0];
134+
let last_selected;
135+
while (tab_header.firstChild) {
136+
let child = tab_header.firstChild;
137+
if (child.className == 'selected') {
138+
last_selected = child.innerHTML;
139+
}
140+
tab_header.removeChild(child);
145141
}
146-
tab_header.removeChild(child);
147-
}
148142

149-
let condemned_textareas = output.getElementsByTagName('TEXTAREA');
150-
let last_scroll = 0;
151-
while (condemned_textareas[0]) {
152-
if (condemned_textareas[0].classList.contains('selected')) {
153-
last_scroll = condemned_textareas[0].scrollTop;
143+
let condemned_textareas = output.getElementsByTagName('TEXTAREA');
144+
let last_scroll = 0;
145+
while (condemned_textareas[0]) {
146+
if (condemned_textareas[0].classList.contains('selected')) {
147+
last_scroll = condemned_textareas[0].scrollTop;
148+
}
149+
output.removeChild(condemned_textareas[0]);
154150
}
155-
output.removeChild(condemned_textareas[0]);
156-
}
157151

158152

159-
let input_files_content = {};
160-
for (let id in input_files) {
161-
let file = input_files[id];
162-
let file_editor = editor_by_textarea_id[id];
163-
input_files_content[file] = file_editor.getValue();
164-
}
165-
function add_textarea_and_tab(filename, selected, scroll, output_content, output_class) {
166-
let output_textarea = document.createElement('TEXTAREA');
167-
let id = 'output-' + counter++;
168-
output_textarea.setAttribute('id', id);
169-
output_textarea.value = output_content;
170-
output.appendChild(output_textarea);
153+
let input_files_content = {};
154+
for (let id in input_files) {
155+
let file = input_files[id];
156+
let file_editor = editor_by_textarea_id[id];
157+
input_files_content[file] = file_editor.getValue();
158+
}
159+
function add_textarea_and_tab(filename, selected, scroll, output_content, output_class) {
160+
let output_textarea = document.createElement('TEXTAREA');
161+
let id = 'output-' + counter++;
162+
output_textarea.setAttribute('id', id);
163+
output_textarea.value = output_content;
164+
output.appendChild(output_textarea);
171165

172-
let selected_class = 'unselected';
173-
if (filename == selected) {
174-
selected_class = 'selected';
175-
output_textarea.scrollTop = scroll;
166+
let selected_class = 'unselected';
167+
if (filename == selected) {
168+
selected_class = 'selected';
169+
output_textarea.scrollTop = scroll;
170+
}
171+
output_textarea.className = selected_class + ' ' + output_class;
172+
let max_height = 300;
173+
for (let id in editor_by_textarea_id) {
174+
let editor_div = editor_by_textarea_id[id].getWrapperElement();
175+
max_height = Math.max(max_height, editor_div.offsetHeight);
176+
}
177+
resize_textarea_max(max_height, output_textarea);
178+
179+
let output_tab = document.createElement('DIV');
180+
tab_header.appendChild(output_tab);
181+
output_tab.className = selected_class;
182+
output_tab.onclick = function() { tab_output_click(this, output_textarea.id); };
183+
output_tab.innerHTML = filename;
176184
}
177-
output_textarea.className = selected_class + ' ' + output_class;
178-
let max_height = 300;
179-
for (let id in editor_by_textarea_id) {
180-
let editor_div = editor_by_textarea_id[id].getWrapperElement();
181-
max_height = Math.max(max_height, editor_div.offsetHeight);
185+
try {
186+
await process_func(
187+
main_file, input_files_content, last_selected, last_scroll, add_textarea_and_tab);
188+
} catch (e) {
189+
if (typeof e === 'string') {
190+
// Remove last \n
191+
e = e.replace(/\n$/, '');
192+
}
193+
add_textarea_and_tab(last_selected, last_selected, last_scroll, e, 'code-error');
182194
}
183-
resize_textarea_max(max_height, output_textarea);
184-
185-
let output_tab = document.createElement('DIV');
186-
tab_header.appendChild(output_tab);
187-
output_tab.className = selected_class;
188-
output_tab.onclick = function() { tab_output_click(this, output_textarea.id); };
189-
output_tab.innerHTML = filename;
190-
}
191-
try {
192-
await process_func(
193-
main_file, input_files_content, last_selected, last_scroll, add_textarea_and_tab);
194195
} catch (e) {
195-
if (typeof e === 'string') {
196-
// Remove last \n
197-
e = e.replace(/\n$/, '');
198-
}
199-
add_textarea_and_tab(last_selected, last_selected, last_scroll, e, 'code-error');
196+
console.error(`error while processing CodeMirror edit/change: ${e}`);
200197
}
201-
} finally {
202-
finishedJobId = Math.max(finishedJobId, currJobId);
203-
}
198+
}));
204199
});
205200
}
206201

0 commit comments

Comments
 (0)