diff --git a/src/main/ts/ObservableValue.ts b/src/main/ts/ObservableValue.ts new file mode 100644 --- /dev/null +++ b/src/main/ts/ObservableValue.ts @@ -0,0 +1,33 @@ +import { Observable } from "./Observable"; +import { IDestroyable } from "./interfaces"; +import { argumentNotNull } from "./safe"; + +type Handler = (x: T) => void; + +export class ObservableValue extends Observable { + private _value: T; + + constructor(initial: T) { + super(); + this._value = initial; + } + + getValue() { + return this._value; + } + + setValue(value: T) { + this._value = value; + this._notifyNext(value); + } + + on(next: Handler, error?: Handler, complete?: () => void): IDestroyable { + argumentNotNull(next, "next"); + try { + next(this._value); + } catch { + // suppress error + } + return super.on(next, error, complete); + } +} diff --git a/src/main/ts/safe.ts b/src/main/ts/safe.ts --- a/src/main/ts/safe.ts +++ b/src/main/ts/safe.ts @@ -153,7 +153,7 @@ export function each(obj, cb, thisArg?) * own properties of the source are entirely copied to the destination. * */ -export function mixin(dest: T, source: S, template?: string[] | object): T & S { +export function mixin(dest: T, source: S, template?: string[] | object): T & S { argumentNotNull(dest, "to"); const _res = dest as T & S; @@ -232,7 +232,6 @@ type _AnyFn = (...args) => any; export function delegate(target: T, _method: (K | _AnyFn)) { let method; - if (!(_method instanceof Function)) { argumentNotNull(target, "target"); method = target[_method]; @@ -264,74 +263,73 @@ export function delay(timeMs: number, ct } /** - * Для каждого элемента массива вызывает указанную функцию и сохраняет - * возвращенное значение в массиве результатов. + * Iterates over the specified array of items and calls the callback `cb`, if + * the result of the callback is a promise the next item from the array will be + * proceeded after the promise is resolved. * - * @remarks cb может выполняться асинхронно, при этом одновременно будет - * только одна операция. - * - * @async */ -export function pmap(items, cb) { +export function pmap( + items: ArrayLike | PromiseLike>, + cb: (item: T, i: number) => T2 | PromiseLike +): T2[] | PromiseLike { argumentNotNull(cb, "cb"); - if (isPromise(items)) + if (isPromise(items)) { return items.then(data => pmap(data, cb)); - - if (isNull(items) || !items.length) - return items; + } else { - let i = 0; - const result = []; + if (isNull(items) || !items.length) + return []; - function next() { - let r; - let ri; + let i = 0; + const result = new Array(); - function chain(x) { - result[ri] = x; - return next(); - } + const next = () => { + while (i < items.length) { + const r = cb(items[i], i); + const ri = i; + i++; + if (isPromise(r)) { + return r.then(x => { + result[ri] = x; + return next(); + }); + } else { + result[ri] = r; + } + } + return result; + }; - while (i < items.length) { - r = cb(items[i], i); - ri = i; - i++; - if (isPromise(r)) { - return r.then(chain); - } else { - result[ri] = r; - } - } - return result; + return next(); } - - return next(); } -export function pfor(items, cb) { +export function pfor( + items: ArrayLike | PromiseLike>, + cb: (item: T, i: number) => any +): void | PromiseLike { argumentNotNull(cb, "cb"); - if (isPromise(items)) - return items.then(data => { - return pmap(data, cb); - }); + if (isPromise(items)) { + return items.then(data => pfor(data, cb)); + } else { + if (isNull(items) || !items.length) + return; - if (isNull(items) || !items.length) - return items; - - let i = 0; + let i = 0; - function next() { - while (i < items.length) { - const r = cb(items[i], i); - i++; - if (isPromise(r)) - return r.then(next); - } + const next = () => { + while (i < items.length) { + const r = cb(items[i], i); + i++; + if (isPromise(r)) + return r.then(next); + } + }; + + return next(); } - - return next(); } export function first(sequence: ArrayLike): T; @@ -368,13 +366,13 @@ export function first( else throw new Error("The sequence is empty"); } else if (cb) { - cb(sequence[0]); + return cb(sequence[0]); } else { return sequence[0]; } } else { if (err) - err(new Error("The sequence is required")); + return err(new Error("The sequence is required")); else throw new Error("The sequence is required"); } diff --git a/src/main/ts/text/FormatCompiler.ts b/src/main/ts/text/FormatCompiler.ts --- a/src/main/ts/text/FormatCompiler.ts +++ b/src/main/ts/text/FormatCompiler.ts @@ -34,17 +34,21 @@ export class FormatCompiler { this.pushSubst(fieldName, filedFormat); } + pushSubst(fieldName: string, filedFormat: string) { throw new Error("Method not implemented."); } + readFieldFormat(scanner: FormatScanner): string { throw new Error("Method not implemented."); } + readColon(scanner: FormatScanner) { if (!scanner.next()) this.dieUnexpectedEnd(); if (scanner.getTokenType() !== TokeType.Colon) return false; + } pushText(text: string) {