Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/lib/promise_utils.js
Views: 789
function sleep (ms) {1return new Promise(resolve => setTimeout(resolve, ms))2}34function createTask () {5const task = {6done: false7}8task.promise = new Promise((resolve, reject) => {9task.cancel = (err) => {10if (!task.done) {11task.done = true12reject(err)13}14}15task.finish = (result) => {16if (!task.done) {17task.done = true18resolve(result)19}20}21})22return task23}2425function createDoneTask () {26const task = {27done: true,28promise: Promise.resolve(),29cancel: () => {},30finish: () => {}31}32return task33}3435/**36* Similar to the 'once' function from the 'events' module, but allows you to add a condition for when you want to37* actually handle the event, as well as a timeout. The listener is additionally removed if a timeout occurs, instead38* of with 'once' where a listener might stay forever if it never triggers.39* Note that timeout and checkCondition, both optional, are in the third parameter as an object.40* @param emitter - The event emitter to listen to41* @param event - The name of the event you want to listen for42* @param [timeout=0] - An amount, in milliseconds, for which to wait before considering the promise failed. <0 = none.43* @param [checkCondition] - A function which matches the same signature of an event emitter handler, and should return something truthy if you want the event to be handled. If this is not provided, all events are handled.44* @returns {Promise} A promise which will either resolve to an *array* of values in the handled event, or will reject on timeout if applicable. This may never resolve if no timeout is set and the event does not fire.45*/46function onceWithCleanup (emitter, event, { timeout = 0, checkCondition = undefined } = {}) {47const task = createTask()4849const onEvent = (...data) => {50if (typeof checkCondition === 'function' && !checkCondition(...data)) {51return52}5354task.finish(data)55}5657emitter.addListener(event, onEvent)5859if (typeof timeout === 'number' && timeout > 0) {60// For some reason, the call stack gets lost if we don't create the error outside of the .then call61const timeoutError = new Error(`Event ${event} did not fire within timeout of ${timeout}ms`)62sleep(timeout).then(() => {63if (!task.done) {64task.cancel(timeoutError)65}66})67}6869task.promise.catch(() => {}).finally(() => emitter.removeListener(event, onEvent))7071return task.promise72}7374function once (emitter, event, timeout = 20000) {75return onceWithCleanup(emitter, event, { timeout })76}7778function withTimeout (promise, timeout) {79return Promise.race([80promise,81sleep(timeout).then(() => {82throw new Error('Promise timed out.')83})84])85}8687module.exports = {88once,89sleep,90createTask,91createDoneTask,92onceWithCleanup,93withTimeout94}959697