autosave: make requests time out

This avoids recent requests being stuck because an older request never
finished.
This commit is contained in:
Pierre de La Morinerie 2019-11-19 16:55:36 +00:00
parent 68f5aae99d
commit 6de5c0c9d1
3 changed files with 18 additions and 3 deletions

View file

@ -1,7 +1,10 @@
import { fire } from '@utils';
import { fire, timeoutable } from '@utils';
// Manages a queue of Autosave operations,
// and sends `autosave:*` events to indicate the state of the requests.
export default class AutosaveController {
constructor() {
this.timeoutDelay = 60000; // 1mn
this.latestPromise = Promise.resolve();
}
@ -47,7 +50,9 @@ export default class AutosaveController {
});
});
return autosavePromise;
// Time out the request after a while, to avoid recent requests not starting
// because an older one is stuck.
return timeoutable(autosavePromise, this.timeoutDelay);
}
// Extract a FormData object of the form fields.

View file

@ -14,7 +14,7 @@ const AUTOSAVE_DEBOUNCE_DELAY = gon.autosave.debounce_delay;
const AUTOSAVE_STATUS_VISIBLE_DURATION = gon.autosave.status_visible_duration;
// Create a controller responsible for queuing autosave operations.
const autosaveController = new AutosaveController(AUTOSAVE_DEBOUNCE_DELAY);
const autosaveController = new AutosaveController();
// Whenever a 'change' event is triggered on one of the form inputs, try to autosave.

View file

@ -86,6 +86,16 @@ function offset(element) {
};
}
// Takes a promise, and return a promise that times out after the given delay.
export function timeoutable(promise, timeoutDelay) {
let timeoutPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error(`Promise timed out after ${timeoutDelay}ms`));
}, timeoutDelay);
});
return Promise.race([promise, timeoutPromise]);
}
const DATA_ACTIVE_REQUESTS_COUNT = 'data-active-requests-count';
function incrementActiveRequestsCount() {