microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.11.2

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/common/node/promise.ts

235lines · modeblame

2f10b3adunknown10 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
ab0238b7RedMickey4 years ago4import { CancellationTokenSource, Disposable } from "vscode";
f338085detatanova4 years ago5
2f10b3adunknown10 years ago6/**
7* Utilities for working with promises.
8*/
34ec0375Daniel10 years ago9export class PromiseUtil {
0d77292aJiglioNero4 years ago10public static async forEach<T>(
11sources: T[],
12promiseGenerator: (source: T) => Promise<void>,
13): Promise<void> {
09f6024fHeniker4 years ago14await Promise.all(sources.map(source => promiseGenerator(source)));
52f3873ddigeff10 years ago15}
2f10b3adunknown10 years ago16/**
17* Retries an operation a given number of times. For each retry, a condition is checked.
18* If the condition is not satisfied after the maximum number of retries, and error is thrown.
19* Otherwise, the result of the operation is returned once the condition is satisfied.
20*
21* @param operation - the function to execute.
22* @param condition - the condition to check between iterations.
23* @param maxRetries - the maximum number of retries.
24* @param delay - time between iterations, in milliseconds.
25* @param failure - error description.
26*/
0d77292aJiglioNero4 years ago27public static retryAsync<T>(
34472878RedMickey5 years ago28operation: () => Promise<T>,
29condition: (result: T) => boolean | Promise<boolean>,
30maxRetries: number,
31delay: number,
32failure: string,
f338085detatanova4 years ago33cancellationTokenSource?: CancellationTokenSource,
34472878RedMickey5 years ago34): Promise<T> {
f338085detatanova4 years ago35return this.retryAsyncIteration(
36operation,
37condition,
38maxRetries,
390,
40delay,
41failure,
42cancellationTokenSource,
43);
2f10b3adunknown10 years ago44}
45
0d77292aJiglioNero4 years ago46public static async reduce<T>(
34472878RedMickey5 years ago47sources: T[] | Promise<T[]>,
48generateAsyncOperation: (value: T) => Promise<void>,
49): Promise<void> {
09f6024fHeniker4 years ago50const arraySources: T[] = sources instanceof Promise ? await sources : sources;
0d77292aJiglioNero4 years ago51
52return arraySources.reduce(async (previousReduction: Promise<void>, newSource: T) => {
53await previousReduction;
54return generateAsyncOperation(newSource);
55}, Promise.resolve());
bc6696cbdigeff10 years ago56}
57
259c018fYuri Skorokhodov5 years ago58public static async delay(duration: number): Promise<void> {
09f6024fHeniker4 years ago59return new Promise<void>(resolve => {
60setTimeout(resolve, duration);
61});
d9c9ddcbRedMickey6 years ago62}
63
ab0238b7RedMickey4 years ago64public static waitUntil<T>(
65condition: () => Promise<T | null> | T | null,
66interval: number = 1000,
67timeout?: number,
68): Promise<T | null> {
8df9830bSamriel4 years ago69return new Promise(async (resolve, reject) => {
ab0238b7RedMickey4 years ago70let rejectTimeout: NodeJS.Timeout | undefined;
09f6024fHeniker4 years ago71// eslint-disable-next-line prefer-const
ab0238b7RedMickey4 years ago72let сheckInterval: NodeJS.Timeout | undefined;
73
74if (timeout) {
75rejectTimeout = setTimeout(() => {
09f6024fHeniker4 years ago76// eslint-disable-next-line @typescript-eslint/no-use-before-define
ab0238b7RedMickey4 years ago77cleanup();
78resolve(null);
79}, timeout);
80}
81
82const cleanup = () => {
83if (rejectTimeout) {
84clearTimeout(rejectTimeout);
85}
86if (сheckInterval) {
87clearInterval(сheckInterval);
88}
89};
90
91const tryToResolve = async (): Promise<boolean> => {
8df9830bSamriel4 years ago92try {
93const result = await condition();
94if (result) {
95cleanup();
96resolve(result);
97}
98return !!result;
99} catch (err) {
ab0238b7RedMickey4 years ago100cleanup();
8df9830bSamriel4 years ago101reject(err);
102return false;
ab0238b7RedMickey4 years ago103}
104};
105
106const resolved = await tryToResolve();
107if (resolved) {
108return;
109}
110
111сheckInterval = setInterval(async () => {
112await tryToResolve();
113}, interval);
114});
115}
116
4bb0956eRedMickey5 years ago117public static promiseCacheDecorator<T>(
118func: (...args: any[]) => Promise<T>,
119context: Record<string, any> | null = null,
120): (...args: any[]) => Promise<T> {
09f6024fHeniker4 years ago121let promise: Promise<T> | undefined;
4bb0956eRedMickey5 years ago122return (...args: any[]): Promise<T> => {
0d77292aJiglioNero4 years ago123if (!promise) {
09f6024fHeniker4 years ago124promise = func.apply(context, args) as Promise<T>;
4bb0956eRedMickey5 years ago125}
0d77292aJiglioNero4 years ago126return promise;
4bb0956eRedMickey5 years ago127};
128}
129
0d77292aJiglioNero4 years ago130private static async retryAsyncIteration<T>(
34472878RedMickey5 years ago131operation: () => Promise<T>,
132condition: (result: T) => boolean | Promise<boolean>,
133maxRetries: number,
134iteration: number,
135delay: number,
136failure: string,
f338085detatanova4 years ago137cancellationTokenSource?: CancellationTokenSource,
34472878RedMickey5 years ago138): Promise<T> {
0d77292aJiglioNero4 years ago139const result = await operation();
140const conditionResult = await condition(result);
141if (conditionResult) {
142return result;
143}
b7451aefRedMickey6 years ago144
0d77292aJiglioNero4 years ago145if (
146iteration < maxRetries &&
147!(cancellationTokenSource && cancellationTokenSource.token.isCancellationRequested)
148) {
149await PromiseUtil.delay(delay);
150return this.retryAsyncIteration(
151operation,
152condition,
153maxRetries,
154iteration + 1,
155delay,
156failure,
157cancellationTokenSource,
158);
159}
b7451aefRedMickey6 years ago160
0d77292aJiglioNero4 years ago161throw new Error(failure);
b7451aefRedMickey6 years ago162}
34472878RedMickey5 years ago163}
ab0238b7RedMickey4 years ago164
165export class Delayer<T> implements Disposable {
166private timeout: any;
167private completionPromise: Promise<any> | null;
168private doResolve: ((value?: any | Promise<any>) => void) | null;
169private doReject: ((err: any) => void) | null;
170private task: { (): T | Promise<T> } | null;
171
172constructor() {
173this.timeout = null;
174this.completionPromise = null;
175this.doResolve = null;
176this.doReject = null;
177this.task = null;
178}
179
180public runWihtDelay(task: { (): T | Promise<T> }, delay: number): Promise<T> {
181this.task = task;
182this.cancelTimeout();
183
184if (!this.completionPromise) {
185this.completionPromise = new Promise((resolve, reject) => {
186this.doResolve = resolve;
187this.doReject = reject;
188}).then(() => {
189this.completionPromise = null;
190this.doResolve = null;
191if (this.task) {
192const task = this.task;
193this.task = null;
194return task();
195}
196return undefined;
197});
198}
199
200this.timeout = setTimeout(() => {
201this.timeout = null;
202if (this.doResolve) {
203this.doResolve(null);
204}
205}, delay);
206
207return this.completionPromise;
208}
209
210public isRunning(): boolean {
211return this.timeout !== null;
212}
213
214public cancel(): void {
215this.cancelTimeout();
216
217if (this.completionPromise) {
218if (this.doReject) {
219this.doReject(new Error("Canceled"));
220}
221this.completionPromise = null;
222}
223}
224
225public dispose(): void {
226this.cancel();
227}
228
229private cancelTimeout(): void {
230if (this.timeout !== null) {
231clearTimeout(this.timeout);
232this.timeout = null;
233}
234}
235}