mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-13 09:14:37 +01:00
ObservablePromise cleanup
This commit is contained in:
committed by
Henning Dieterichs
parent
e713ba0fb9
commit
bc7e1fc609
@@ -49,15 +49,20 @@ export {
|
||||
} from 'vs/base/common/observableInternal/utils';
|
||||
export {
|
||||
ObservableLazy,
|
||||
ObservableLazyStatefulPromise,
|
||||
ObservableLazyPromise,
|
||||
ObservablePromise,
|
||||
PromiseResult,
|
||||
waitForState,
|
||||
derivedWithCancellationToken,
|
||||
} from 'vs/base/common/observableInternal/promise';
|
||||
|
||||
import { ConsoleObservableLogger, setLogger } from 'vs/base/common/observableInternal/logging';
|
||||
|
||||
const enableLogging = false;
|
||||
// Remove "//" in the next line to enable logging
|
||||
const enableLogging = false
|
||||
// || Boolean("true") // done "weirdly" so that a lint warning prevents you from pushing this
|
||||
;
|
||||
|
||||
if (enableLogging) {
|
||||
setLogger(new ConsoleObservableLogger());
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { DebugNameData, IDebugNameData, Owner } from 'vs/base/common/observableI
|
||||
import { getLogger } from 'vs/base/common/observableInternal/logging';
|
||||
|
||||
export type EqualityComparer<T> = (a: T, b: T) => boolean;
|
||||
const defaultEqualityComparer: EqualityComparer<any> = (a, b) => a === b;
|
||||
export const defaultEqualityComparer: EqualityComparer<any> = (a, b) => a === b;
|
||||
|
||||
/**
|
||||
* Creates an observable that is derived from other observables.
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { autorun } from 'vs/base/common/observableInternal/autorun';
|
||||
import { IObservable, observableValue } from './base';
|
||||
import { derived } from 'vs/base/common/observableInternal/derived';
|
||||
import { IObservable, IReader, observableValue, transaction } from './base';
|
||||
import { Derived, defaultEqualityComparer, derived } from 'vs/base/common/observableInternal/derived';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { DebugNameData, Owner } from 'vs/base/common/observableInternal/debugName';
|
||||
|
||||
export class ObservableLazy<T> {
|
||||
private readonly _value = observableValue<T | undefined>(this, undefined);
|
||||
@@ -38,15 +40,29 @@ export class ObservableLazy<T> {
|
||||
export class ObservablePromise<T> {
|
||||
private readonly _value = observableValue<PromiseResult<T> | undefined>(this, undefined);
|
||||
|
||||
/**
|
||||
* The promise that this object wraps.
|
||||
*/
|
||||
public readonly promise: Promise<T>;
|
||||
public readonly value: IObservable<PromiseResult<T> | undefined> = this._value;
|
||||
|
||||
/**
|
||||
* The current state of the promise.
|
||||
* Is `undefined` if the promise didn't resolve yet.
|
||||
*/
|
||||
public readonly promiseResult: IObservable<PromiseResult<T> | undefined> = this._value;
|
||||
|
||||
constructor(promise: Promise<T>) {
|
||||
this.promise = promise.then(value => {
|
||||
this._value.set(new PromiseResult(value, undefined), undefined);
|
||||
transaction(tx => {
|
||||
/** @description onPromiseResolved */
|
||||
this._value.set(new PromiseResult(value, undefined), tx);
|
||||
});
|
||||
return value;
|
||||
}, error => {
|
||||
this._value.set(new PromiseResult<T>(undefined, error), undefined);
|
||||
transaction(tx => {
|
||||
/** @description onPromiseRejected */
|
||||
this._value.set(new PromiseResult<T>(undefined, error), tx);
|
||||
});
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
@@ -58,7 +74,7 @@ export class PromiseResult<T> {
|
||||
* The value of the resolved promise.
|
||||
* Undefined if the promise rejected.
|
||||
*/
|
||||
public readonly value: T | undefined,
|
||||
public readonly data: T | undefined,
|
||||
|
||||
/**
|
||||
* The error in case of a rejected promise.
|
||||
@@ -71,30 +87,30 @@ export class PromiseResult<T> {
|
||||
/**
|
||||
* Returns the value if the promise resolved, otherwise throws the error.
|
||||
*/
|
||||
public getValue(): T {
|
||||
public getDataOrThrow(): T {
|
||||
if (this.error) {
|
||||
throw this.error;
|
||||
}
|
||||
return this.value!;
|
||||
return this.data!;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A lazy promise whose state is observable.
|
||||
*/
|
||||
export class ObservableLazyStatefulPromise<T> {
|
||||
private readonly _lazyValue = new ObservableLazy(() => new ObservablePromise(this._computeValue()));
|
||||
export class ObservableLazyPromise<T> {
|
||||
private readonly _lazyValue = new ObservableLazy(() => new ObservablePromise(this._computePromise()));
|
||||
|
||||
/**
|
||||
* Does not enforce evaluation of the promise compute function.
|
||||
* Is undefined if the promise has not been computed yet.
|
||||
*/
|
||||
public readonly cachedValue = derived(this, reader => this._lazyValue.cachedValue.read(reader)?.value.read(reader));
|
||||
public readonly cachedPromiseResult = derived(this, reader => this._lazyValue.cachedValue.read(reader)?.promiseResult.read(reader));
|
||||
|
||||
constructor(private readonly _computeValue: () => Promise<T>) {
|
||||
constructor(private readonly _computePromise: () => Promise<T>) {
|
||||
}
|
||||
|
||||
public getValue(): Promise<T> {
|
||||
public getPromise(): Promise<T> {
|
||||
return this._lazyValue.getValue().promise;
|
||||
}
|
||||
}
|
||||
@@ -139,3 +155,32 @@ export function waitForState<T>(observable: IObservable<T>, predicate: (state: T
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function derivedWithCancellationToken<T>(computeFn: (reader: IReader, cancellationToken: CancellationToken) => T): IObservable<T>;
|
||||
export function derivedWithCancellationToken<T>(owner: object, computeFn: (reader: IReader, cancellationToken: CancellationToken) => T): IObservable<T>;
|
||||
export function derivedWithCancellationToken<T>(computeFnOrOwner: ((reader: IReader, cancellationToken: CancellationToken) => T) | object, computeFnOrUndefined?: ((reader: IReader, cancellationToken: CancellationToken) => T)): IObservable<T> {
|
||||
let computeFn: (reader: IReader, store: CancellationToken) => T;
|
||||
let owner: Owner;
|
||||
if (computeFnOrUndefined === undefined) {
|
||||
computeFn = computeFnOrOwner as any;
|
||||
owner = undefined;
|
||||
} else {
|
||||
owner = computeFnOrOwner;
|
||||
computeFn = computeFnOrUndefined as any;
|
||||
}
|
||||
|
||||
let cancellationTokenSource: CancellationTokenSource | undefined = undefined;
|
||||
return new Derived(
|
||||
new DebugNameData(owner, undefined, computeFn),
|
||||
r => {
|
||||
if (cancellationTokenSource) {
|
||||
cancellationTokenSource.dispose(true);
|
||||
}
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
return computeFn(r, cancellationTokenSource.token);
|
||||
}, undefined,
|
||||
undefined,
|
||||
() => cancellationTokenSource?.dispose(),
|
||||
defaultEqualityComparer,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Disposable, DisposableStore, IDisposable, IReference, toDisposable } fr
|
||||
import { parse } from 'vs/base/common/marshalling';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { ObservableLazyStatefulPromise, autorun, derived, observableFromEvent } from 'vs/base/common/observable';
|
||||
import { ObservableLazyPromise, autorun, derived, observableFromEvent } from 'vs/base/common/observable';
|
||||
import { constObservable, mapObservableArrayCached } from 'vs/base/common/observableInternal/utils';
|
||||
import { ThemeIcon } from 'vs/base/common/themables';
|
||||
import { isDefined, isObject } from 'vs/base/common/types';
|
||||
@@ -131,7 +131,7 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
||||
});
|
||||
|
||||
private async _createModel(): Promise<IMultiDiffEditorModel & IDisposable> {
|
||||
const source = await this._resolvedSource.getValue();
|
||||
const source = await this._resolvedSource.getPromise();
|
||||
const textResourceConfigurationService = this._textResourceConfigurationService;
|
||||
|
||||
// Enables delayed disposing
|
||||
@@ -207,7 +207,7 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
||||
};
|
||||
}
|
||||
|
||||
private readonly _resolvedSource = new ObservableLazyStatefulPromise(async () => {
|
||||
private readonly _resolvedSource = new ObservableLazyPromise(async () => {
|
||||
const source: IResolvedMultiDiffSource | undefined = this.initialResources
|
||||
? new ConstResolvedMultiDiffSource(this.initialResources)
|
||||
: await this._multiDiffSourceResolverService.resolve(this.multiDiffSource);
|
||||
@@ -229,7 +229,7 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
||||
return false;
|
||||
}
|
||||
|
||||
private readonly _resources = derived(this, reader => this._resolvedSource.cachedValue.read(reader)?.value?.resources.read(reader));
|
||||
private readonly _resources = derived(this, reader => this._resolvedSource.cachedPromiseResult.read(reader)?.data?.resources.read(reader));
|
||||
private readonly _isDirtyObservables = mapObservableArrayCached(this, this._resources.map(r => r || []), res => {
|
||||
const isModifiedDirty = res.modified ? isUriDirty(this._textFileService, res.modified) : constObservable(false);
|
||||
const isOriginalDirty = res.original ? isUriDirty(this._textFileService, res.original) : constObservable(false);
|
||||
|
||||
Reference in New Issue
Block a user