UNPKG

5.08 kBJavaScriptView Raw
1"use strict";
2// *****************************************************************************
3// Copyright (C) 2017 TypeFox and others.
4//
5// This program and the accompanying materials are made available under the
6// terms of the Eclipse Public License v. 2.0 which is available at
7// http://www.eclipse.org/legal/epl-2.0.
8//
9// This Source Code may also be made available under the following Secondary
10// Licenses when the conditions for such availability set forth in the Eclipse
11// Public License v. 2.0 are satisfied: GNU General Public License, version 2
12// with the GNU Classpath Exception which is available at
13// https://www.gnu.org/software/classpath/license.html.
14//
15// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16// *****************************************************************************
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.firstTrue = exports.isThenable = exports.waitForEvent = exports.wait = exports.delay = exports.retry = exports.timeoutReject = exports.timeout = exports.Deferred = void 0;
19const cancellation_1 = require("./cancellation");
20const types_1 = require("./types");
21/**
22 * Simple implementation of the deferred pattern.
23 * An object that exposes a promise and functions to resolve and reject it.
24 */
25class Deferred {
26 constructor() {
27 this.state = 'unresolved';
28 this.promise = new Promise((resolve, reject) => {
29 this.resolve = resolve;
30 this.reject = reject;
31 }).then(res => (this.setState('resolved'), res), err => (this.setState('rejected'), Promise.reject(err)));
32 }
33 setState(state) {
34 if (this.state === 'unresolved') {
35 this.state = state;
36 }
37 }
38}
39exports.Deferred = Deferred;
40/**
41 * @returns resolves after a specified number of milliseconds
42 * @throws cancelled if a given token is cancelled before a specified number of milliseconds
43 */
44function timeout(ms, token = cancellation_1.CancellationToken.None) {
45 const deferred = new Deferred();
46 const handle = setTimeout(() => deferred.resolve(), ms);
47 token.onCancellationRequested(() => {
48 clearTimeout(handle);
49 deferred.reject((0, cancellation_1.cancelled)());
50 });
51 return deferred.promise;
52}
53exports.timeout = timeout;
54/**
55 * Creates a promise that is rejected after the given amount of time. A typical use case is to wait for another promise until a specified timeout using:
56 * ```
57 * Promise.race([ promiseToPerform, timeoutReject(timeout, 'Timeout error message') ]);
58 * ```
59 *
60 * @param ms timeout in milliseconds
61 * @param message error message on promise rejection
62 * @returns rejection promise
63 */
64function timeoutReject(ms, message) {
65 const deferred = new Deferred();
66 setTimeout(() => deferred.reject(new Error(message)), ms);
67 return deferred.promise;
68}
69exports.timeoutReject = timeoutReject;
70async function retry(task, retryDelay, retries) {
71 let lastError;
72 for (let i = 0; i < retries; i++) {
73 try {
74 return await task();
75 }
76 catch (error) {
77 lastError = error;
78 await timeout(retryDelay);
79 }
80 }
81 throw lastError;
82}
83exports.retry = retry;
84/**
85 * A function to allow a promise resolution to be delayed by a number of milliseconds. Usage is as follows:
86 *
87 * `const stringValue = await myPromise.then(delay(600)).then(value => value.toString());`
88 *
89 * @param ms the number of millisecond to delay
90 * @returns a function that returns a promise that returns the given value, but delayed
91 */
92function delay(ms) {
93 return value => new Promise((resolve, reject) => { setTimeout(() => resolve(value), ms); });
94}
95exports.delay = delay;
96/**
97 * Constructs a promise that will resolve after a given delay.
98 * @param ms the number of milliseconds to wait
99 */
100async function wait(ms) {
101 await delay(ms)(undefined);
102}
103exports.wait = wait;
104// eslint-disable-next-line @typescript-eslint/no-explicit-any
105function waitForEvent(event, ms, thisArg, disposables) {
106 return new Promise((resolve, reject) => {
107 const registration = setTimeout(() => {
108 listener.dispose();
109 reject(new cancellation_1.CancellationError());
110 }, ms);
111 const listener = event((evt) => {
112 clearTimeout(registration);
113 listener.dispose();
114 resolve(evt);
115 }, thisArg, disposables);
116 });
117}
118exports.waitForEvent = waitForEvent;
119function isThenable(obj) {
120 return (0, types_1.isObject)(obj) && (0, types_1.isFunction)(obj.then);
121}
122exports.isThenable = isThenable;
123/**
124 * Returns with a promise that waits until the first promise resolves to `true`.
125 */
126// Based on https://stackoverflow.com/a/51160727/5529090
127function firstTrue(...promises) {
128 const newPromises = promises.map(promise => new Promise((resolve, reject) => promise.then(result => result && resolve(true), reject)));
129 newPromises.push(Promise.all(promises).then(() => false));
130 return Promise.race(newPromises);
131}
132exports.firstTrue = firstTrue;
133//# sourceMappingURL=promise-util.js.map
\No newline at end of file