UNPKG

2.48 kBJavaScriptView Raw
1/**
2 * Utility helpers to work with promises.
3 *
4 * @module promise
5 */
6
7import * as time from './time.js'
8
9/**
10 * @template T
11 * @callback PromiseResolve
12 * @param {T|PromiseLike<T>} [result]
13 */
14
15/**
16 * @template T
17 * @param {function(PromiseResolve<T>,function(Error):void):any} f
18 * @return {Promise<T>}
19 */
20export const create = f => /** @type {Promise<T>} */ (new Promise(f))
21
22/**
23 * @param {function(function():void,function(Error):void):void} f
24 * @return {Promise<void>}
25 */
26export const createEmpty = f => new Promise(f)
27
28/**
29 * `Promise.all` wait for all promises in the array to resolve and return the result
30 * @template {unknown[] | []} PS
31 *
32 * @param {PS} ps
33 * @return {Promise<{ -readonly [P in keyof PS]: Awaited<PS[P]> }>}
34 */
35export const all = Promise.all.bind(Promise)
36
37/**
38 * @param {Error} [reason]
39 * @return {Promise<never>}
40 */
41export const reject = reason => Promise.reject(reason)
42
43/**
44 * @template T
45 * @param {T|void} res
46 * @return {Promise<T|void>}
47 */
48export const resolve = res => Promise.resolve(res)
49
50/**
51 * @template T
52 * @param {T} res
53 * @return {Promise<T>}
54 */
55export const resolveWith = res => Promise.resolve(res)
56
57/**
58 * @todo Next version, reorder parameters: check, [timeout, [intervalResolution]]
59 *
60 * @param {number} timeout
61 * @param {function():boolean} check
62 * @param {number} [intervalResolution]
63 * @return {Promise<void>}
64 */
65export const until = (timeout, check, intervalResolution = 10) => create((resolve, reject) => {
66 const startTime = time.getUnixTime()
67 const hasTimeout = timeout > 0
68 const untilInterval = () => {
69 if (check()) {
70 clearInterval(intervalHandle)
71 resolve()
72 } else if (hasTimeout) {
73 /* c8 ignore else */
74 if (time.getUnixTime() - startTime > timeout) {
75 clearInterval(intervalHandle)
76 reject(new Error('Timeout'))
77 }
78 }
79 }
80 const intervalHandle = setInterval(untilInterval, intervalResolution)
81})
82
83/**
84 * @param {number} timeout
85 * @return {Promise<undefined>}
86 */
87export const wait = timeout => create((resolve, reject) => setTimeout(resolve, timeout))
88
89/**
90 * Checks if an object is a promise using ducktyping.
91 *
92 * Promises are often polyfilled, so it makes sense to add some additional guarantees if the user of this
93 * library has some insane environment where global Promise objects are overwritten.
94 *
95 * @param {any} p
96 * @return {boolean}
97 */
98export const isPromise = p => p instanceof Promise || (p && p.then && p.catch && p.finally)