microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.8.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/node/promise.ts

234lines · 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> {
14await Promise.all(
34472878RedMickey5 years ago15sources.map(source => {
52f3873ddigeff10 years ago16return promiseGenerator(source);
34472878RedMickey5 years ago17}),
0d77292aJiglioNero4 years ago18);
52f3873ddigeff10 years ago19}
2f10b3adunknown10 years ago20/**
21* Retries an operation a given number of times. For each retry, a condition is checked.
22* If the condition is not satisfied after the maximum number of retries, and error is thrown.
23* Otherwise, the result of the operation is returned once the condition is satisfied.
24*
25* @param operation - the function to execute.
26* @param condition - the condition to check between iterations.
27* @param maxRetries - the maximum number of retries.
28* @param delay - time between iterations, in milliseconds.
29* @param failure - error description.
30*/
0d77292aJiglioNero4 years ago31public static retryAsync<T>(
34472878RedMickey5 years ago32operation: () => Promise<T>,
33condition: (result: T) => boolean | Promise<boolean>,
34maxRetries: number,
35delay: number,
36failure: string,
f338085detatanova4 years ago37cancellationTokenSource?: CancellationTokenSource,
34472878RedMickey5 years ago38): Promise<T> {
f338085detatanova4 years ago39return this.retryAsyncIteration(
40operation,
41condition,
42maxRetries,
430,
44delay,
45failure,
46cancellationTokenSource,
47);
2f10b3adunknown10 years ago48}
49
0d77292aJiglioNero4 years ago50public static async reduce<T>(
34472878RedMickey5 years ago51sources: T[] | Promise<T[]>,
52generateAsyncOperation: (value: T) => Promise<void>,
53): Promise<void> {
0d77292aJiglioNero4 years ago54let arraySources: T[];
ce5e88eeYuri Skorokhodov5 years ago55if (sources instanceof Promise) {
0d77292aJiglioNero4 years ago56arraySources = await sources;
ce5e88eeYuri Skorokhodov5 years ago57} else {
0d77292aJiglioNero4 years ago58arraySources = sources;
ce5e88eeYuri Skorokhodov5 years ago59}
0d77292aJiglioNero4 years ago60
61return arraySources.reduce(async (previousReduction: Promise<void>, newSource: T) => {
62await previousReduction;
63return generateAsyncOperation(newSource);
64}, Promise.resolve());
bc6696cbdigeff10 years ago65}
66
259c018fYuri Skorokhodov5 years ago67public static async delay(duration: number): Promise<void> {
d9c9ddcbRedMickey6 years ago68return new Promise<void>(resolve => setTimeout(resolve, duration));
69}
70
ab0238b7RedMickey4 years ago71public static waitUntil<T>(
72condition: () => Promise<T | null> | T | null,
73interval: number = 1000,
74timeout?: number,
75): Promise<T | null> {
76return new Promise(async resolve => {
77let rejectTimeout: NodeJS.Timeout | undefined;
78let сheckInterval: NodeJS.Timeout | undefined;
79
80if (timeout) {
81rejectTimeout = setTimeout(() => {
82cleanup();
83resolve(null);
84}, timeout);
85}
86
87const cleanup = () => {
88if (rejectTimeout) {
89clearTimeout(rejectTimeout);
90}
91if (сheckInterval) {
92clearInterval(сheckInterval);
93}
94};
95
96const tryToResolve = async (): Promise<boolean> => {
97const result = await condition();
98if (result) {
99cleanup();
100resolve(result);
101}
102return !!result;
103};
104
105const resolved = await tryToResolve();
106if (resolved) {
107return;
108}
109
110сheckInterval = setInterval(async () => {
111await tryToResolve();
112}, interval);
113});
114}
115
4bb0956eRedMickey5 years ago116public static promiseCacheDecorator<T>(
117func: (...args: any[]) => Promise<T>,
118context: Record<string, any> | null = null,
119): (...args: any[]) => Promise<T> {
120let promise: Promise<T>;
121return (...args: any[]): Promise<T> => {
0d77292aJiglioNero4 years ago122if (!promise) {
4bb0956eRedMickey5 years ago123promise = func.apply(context, args);
124}
0d77292aJiglioNero4 years ago125return promise;
4bb0956eRedMickey5 years ago126};
127}
128
0d77292aJiglioNero4 years ago129private static async retryAsyncIteration<T>(
34472878RedMickey5 years ago130operation: () => Promise<T>,
131condition: (result: T) => boolean | Promise<boolean>,
132maxRetries: number,
133iteration: number,
134delay: number,
135failure: string,
f338085detatanova4 years ago136cancellationTokenSource?: CancellationTokenSource,
34472878RedMickey5 years ago137): Promise<T> {
0d77292aJiglioNero4 years ago138const result = await operation();
139const conditionResult = await condition(result);
140if (conditionResult) {
141return result;
142}
b7451aefRedMickey6 years ago143
0d77292aJiglioNero4 years ago144if (
145iteration < maxRetries &&
146!(cancellationTokenSource && cancellationTokenSource.token.isCancellationRequested)
147) {
148await PromiseUtil.delay(delay);
149return this.retryAsyncIteration(
150operation,
151condition,
152maxRetries,
153iteration + 1,
154delay,
155failure,
156cancellationTokenSource,
157);
158}
b7451aefRedMickey6 years ago159
0d77292aJiglioNero4 years ago160throw new Error(failure);
b7451aefRedMickey6 years ago161}
34472878RedMickey5 years ago162}
ab0238b7RedMickey4 years ago163
164export class Delayer<T> implements Disposable {
165private timeout: any;
166private completionPromise: Promise<any> | null;
167private doResolve: ((value?: any | Promise<any>) => void) | null;
168private doReject: ((err: any) => void) | null;
169private task: { (): T | Promise<T> } | null;
170
171constructor() {
172this.timeout = null;
173this.completionPromise = null;
174this.doResolve = null;
175this.doReject = null;
176this.task = null;
177}
178
179public runWihtDelay(task: { (): T | Promise<T> }, delay: number): Promise<T> {
180this.task = task;
181this.cancelTimeout();
182
183if (!this.completionPromise) {
184this.completionPromise = new Promise((resolve, reject) => {
185this.doResolve = resolve;
186this.doReject = reject;
187}).then(() => {
188this.completionPromise = null;
189this.doResolve = null;
190if (this.task) {
191const task = this.task;
192this.task = null;
193return task();
194}
195return undefined;
196});
197}
198
199this.timeout = setTimeout(() => {
200this.timeout = null;
201if (this.doResolve) {
202this.doResolve(null);
203}
204}, delay);
205
206return this.completionPromise;
207}
208
209public isRunning(): boolean {
210return this.timeout !== null;
211}
212
213public cancel(): void {
214this.cancelTimeout();
215
216if (this.completionPromise) {
217if (this.doReject) {
218this.doReject(new Error("Canceled"));
219}
220this.completionPromise = null;
221}
222}
223
224public dispose(): void {
225this.cancel();
226}
227
228private cancelTimeout(): void {
229if (this.timeout !== null) {
230clearTimeout(this.timeout);
231this.timeout = null;
232}
233}
234}