Add type annotations to AsyncMappedList

This commit is contained in:
Danila Fedorin 2021-09-29 19:13:38 -07:00
parent 0e6c59983f
commit 8466a910da

View File

@ -15,15 +15,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseMappedList, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList"; import {IListObserver} from "./BaseObservableList";
import {BaseMappedList, Mapper, Updater, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList";
export class AsyncMappedList extends BaseMappedList { export class AsyncMappedList<F,T> extends BaseMappedList<F,T,Promise<T>> implements IListObserver<F> {
constructor(sourceList, mapper, updater, removeCallback) { private _eventQueue: AsyncEvent<F>[] | null = null;
super(sourceList, mapper, updater, removeCallback); private _flushing: boolean = false;
this._eventQueue = null;
}
onSubscribeFirst() { onSubscribeFirst(): void {
this._sourceUnsubscribe = this._sourceList.subscribe(this); this._sourceUnsubscribe = this._sourceList.subscribe(this);
this._eventQueue = []; this._eventQueue = [];
this._mappedValues = []; this._mappedValues = [];
@ -35,110 +34,100 @@ export class AsyncMappedList extends BaseMappedList {
this._flush(); this._flush();
} }
async _flush() { async _flush(): Promise<void> {
if (this._flushing) { if (this._flushing) {
return; return;
} }
this._flushing = true; this._flushing = true;
try { try {
while (this._eventQueue.length) { while (this._eventQueue!.length) {
const event = this._eventQueue.shift(); const event = this._eventQueue!.shift();
await event.run(this); await event!.run(this);
} }
} finally { } finally {
this._flushing = false; this._flushing = false;
} }
} }
onReset() { onReset(): void {
if (this._eventQueue) { if (this._eventQueue) {
this._eventQueue.push(new ResetEvent()); this._eventQueue.push(new ResetEvent());
this._flush(); this._flush();
} }
} }
onAdd(index, value) { onAdd(index: number, value: F): void {
if (this._eventQueue) { if (this._eventQueue) {
this._eventQueue.push(new AddEvent(index, value)); this._eventQueue.push(new AddEvent(index, value));
this._flush(); this._flush();
} }
} }
onUpdate(index, value, params) { onUpdate(index: number, value: F, params: any): void {
if (this._eventQueue) { if (this._eventQueue) {
this._eventQueue.push(new UpdateEvent(index, value, params)); this._eventQueue.push(new UpdateEvent(index, value, params));
this._flush(); this._flush();
} }
} }
onRemove(index) { onRemove(index: number): void {
if (this._eventQueue) { if (this._eventQueue) {
this._eventQueue.push(new RemoveEvent(index)); this._eventQueue.push(new RemoveEvent(index));
this._flush(); this._flush();
} }
} }
onMove(fromIdx, toIdx) { onMove(fromIdx: number, toIdx: number): void {
if (this._eventQueue) { if (this._eventQueue) {
this._eventQueue.push(new MoveEvent(fromIdx, toIdx)); this._eventQueue.push(new MoveEvent(fromIdx, toIdx));
this._flush(); this._flush();
} }
} }
onUnsubscribeLast() { onUnsubscribeLast(): void {
this._sourceUnsubscribe(); this._sourceUnsubscribe!();
this._eventQueue = null; this._eventQueue = null;
this._mappedValues = null; this._mappedValues = null;
} }
} }
class AddEvent { type AsyncEvent<F> = AddEvent<F> | UpdateEvent<F> | RemoveEvent<F> | MoveEvent<F> | ResetEvent<F>
constructor(index, value) {
this.index = index;
this.value = value;
}
async run(list) { class AddEvent<F> {
constructor(public index: number, public value: F) {}
async run<T>(list: AsyncMappedList<F,T>): Promise<void> {
const mappedValue = await list._mapper(this.value); const mappedValue = await list._mapper(this.value);
runAdd(list, this.index, mappedValue); runAdd(list, this.index, mappedValue);
} }
} }
class UpdateEvent { class UpdateEvent<F> {
constructor(index, value, params) { constructor(public index: number, public value: F, public params: any) {}
this.index = index;
this.value = value;
this.params = params;
}
async run(list) { async run<T>(list: AsyncMappedList<F,T>): Promise<void> {
runUpdate(list, this.index, this.value, this.params); runUpdate(list, this.index, this.value, this.params);
} }
} }
class RemoveEvent { class RemoveEvent<F> {
constructor(index) { constructor(public index: number) {}
this.index = index;
}
async run(list) { async run<T>(list: AsyncMappedList<F,T>): Promise<void> {
runRemove(list, this.index); runRemove(list, this.index);
} }
} }
class MoveEvent { class MoveEvent<F> {
constructor(fromIdx, toIdx) { constructor(public fromIdx: number, public toIdx: number) {}
this.fromIdx = fromIdx;
this.toIdx = toIdx;
}
async run(list) { async run<T>(list: AsyncMappedList<F,T>): Promise<void> {
runMove(list, this.fromIdx, this.toIdx); runMove(list, this.fromIdx, this.toIdx);
} }
} }
class ResetEvent { class ResetEvent<F> {
async run(list) { async run<T>(list: AsyncMappedList<F,T>): Promise<void> {
runReset(list); runReset(list);
} }
} }
@ -150,7 +139,7 @@ export function tests() {
return { return {
"events are emitted in order": async assert => { "events are emitted in order": async assert => {
const double = n => n * n; const double = n => n * n;
const source = new ObservableArray(); const source = new ObservableArray<number>();
const mapper = new AsyncMappedList(source, async n => { const mapper = new AsyncMappedList(source, async n => {
await new Promise(r => setTimeout(r, n)); await new Promise(r => setTimeout(r, n));
return {n: double(n)}; return {n: double(n)};