Use same lock values as mobile clients
[ProtonMail-WebClient.git] / packages / shared / lib / helpers / onceWithQueue.ts
blob3cbdb2d9b8a0bcae716c00e5541b86fb8294c185
1 /**
2  * Ensures that a function returning a promise is only called once at a time.
3  *
4  * If it is called while the previous promise is resolving, another call to the
5  * function will be queued, and run once, with the arguments of the last call
6  * after the previous promise has resolved. The returned promise resolves after
7  * the queued promise resolves.
8  *
9  */
10 export const onceWithQueue = <R>(fn: () => Promise<R>): (() => Promise<R>) => {
11     let STATE: {
12         promise?: Promise<R>;
13         queued?: Promise<R>;
14     } = {};
16     const clear = () => {
17         STATE = {};
18     };
20     const clearPromise = () => {
21         STATE.promise = undefined;
22     };
24     const next = (): Promise<R> => {
25         clear();
26         // eslint-disable-next-line
27         return run();
28     };
30     const run = () => {
31         // If a queue has already been set up, update the arguments.
32         if (STATE.queued) {
33             return STATE.queued;
34         }
36         // If a promise is running, set up the queue.
37         if (STATE.promise) {
38             STATE.queued = STATE.promise.then(next);
39             return STATE.queued;
40         }
42         // Cache the promise.
43         STATE.promise = fn();
44         // Set up independent resolve handlers.
45         STATE.promise.then(clearPromise).catch(clear);
47         return STATE.promise;
48     };
50     return run;