Skip to content

Instantly share code, notes, and snippets.

@Drarig29
Last active January 18, 2023 00:31
Show Gist options
  • Save Drarig29/45f1c8d0d86fc1b5bfbf1aabb70b332d to your computer and use it in GitHub Desktop.
Save Drarig29/45f1c8d0d86fc1b5bfbf1aabb70b332d to your computer and use it in GitHub Desktop.
An IIFE which enqueues a promise in a single promise. Ensures promises are executed in the good order
/**
* Delays a `console.log()` for the given time amount.
*
* @param message A message to log.
* @param duration A delay in seconds.
*/
function delay(message: string, duration: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
console.log(message);
resolve();
}, timeAmount * 1000);
});
}
/**
* An IIFE which enqueues a promise in a single promise. Ensures promises are executed in the good order.
*
* @param promise A promise to enqueue.
*/
const enqueuePromise = (() => {
let queue: Promise<any> | null = null;
return async (promise?: () => any) => {
if (!promise) return queue;
queue = queue ? queue.then(promise) : promise();
return queue = queue && queue.then(() => queue = null);
};
})();
// Useless, but works.
enqueuePromise();
// Enqueue two promises.
enqueuePromise(() => delay('promise 1', 3));
enqueuePromise(() => delay('promise 2', 1));
async function awaitExample() {
// Await for any promise enqueued in the past.
await enqueuePromise();
// Enqueue two promises.
enqueuePromise(() => delay('promise 3', 3));
enqueuePromise(() => delay('promise 4', 1));
// Await for both promises to end.
await enqueuePromise();
console.log('All promises done.');
}
awaitExample();
/**
* Delays a `console.log()` for the given time amount.
*
* @param message A message to log.
* @param timeAmount A delay in seconds.
*/
function delay(message: string, timeAmount: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
console.log(message);
resolve();
}, timeAmount * 1000);
});
}
/**
* A lambda expression.
*/
type Lambda = () => any;
/**
* A queue id.
*/
type QueueId = string | number;
/**
* A queue.
*/
type Queue = (promise?: Lambda) => Promise<any>;
/**
* Returns a queue which joins a promise in a single promise. Ensures promises are executed in the good order.
*/
function makePromiseQueue(): Queue {
return (() => {
let queue: Promise<any> | null = null;
return async (promise?: Lambda) => {
if (!promise) return queue;
queue = queue ? queue.then(promise) : promise();
return queue = queue && queue.then(() => queue = null);
};
})();
}
/**
* Enqueues a promise in the queue.
*/
const enqueuePromise = makePromiseQueue();
/**
* Enqueues a promise in the queue which has the given ID.
*/
const enqueuePromiseWithId = (() => {
const queues: {[id in QueueId]: Queue} = {};
return (id: QueueId) => queues[id] = queues[id] || makePromiseQueue();
})();
// Useless, but just to show that it works.
enqueuePromise();
// Enqueue two promises.
enqueuePromise(() => delay('promise 1', 3));
enqueuePromise(() => delay('promise 2', 1));
async function awaitExample() {
// Await for any promise enqueued in the past.
await enqueuePromise();
// Enqueue two promises.
enqueuePromise(() => delay('promise 3', 3));
enqueuePromise(() => delay('promise 4', 1));
// Await for both promises to end.
await enqueuePromise();
console.log('awaitExample() done.');
}
async function awaitWithIdExample() {
// Enqueue two promises in the first queue (created during the first call).
enqueuePromiseWithId('queue1')(() => delay('promise A (queue1)', 1));
enqueuePromiseWithId('queue1')(() => delay('promise B (queue1)', 0));
// Enqueue two promises in the second queue (created during the first call).
enqueuePromiseWithId('queue2')(() => delay('promise A (queue2)', 1));
enqueuePromiseWithId('queue2')(() => delay('promise B (queue2)', 0));
// Enqueue two promises in the third queue (created during the first call).
enqueuePromiseWithId('queue3')(() => delay('promise A (queue3)', 6));
enqueuePromiseWithId('queue3')(() => delay('promise B (queue3)', 4));
await enqueuePromiseWithId('queue3')();
console.log('awaitWithIdExample() done.');
}
awaitExample();
awaitWithIdExample();
@Drarig29
Copy link
Author

Drarig29 commented Dec 6, 2020

You can see it in the following TS Playground 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment