##// END OF EJS Templates
Fixed circular dependency safe<->Cancellation
cin -
r150:b16ed1178612 v1.4.0-rc7 default
parent child
Show More
@@ -1,502 +1,518
1 import { ICancellable, Constructor, IDestroyable, PromiseOrValue } from "./interfaces";
1 import { ICancellable, Constructor, IDestroyable, ICancellation } from "./interfaces";
2 import { Cancellation } from "./Cancellation";
3
2
4 let _nextOid = 0;
3 let _nextOid = 0;
5 const _oid = typeof Symbol === "function" ?
4 const _oid = typeof Symbol === "function" ?
6 Symbol("__implab__oid__") :
5 Symbol("__implab__oid__") :
7 "__implab__oid__";
6 "__implab__oid__";
8
7
9 export function oid(instance: null | undefined): undefined;
8 export function oid(instance: null | undefined): undefined;
10 export function oid(instance: NonNullable<any>): string;
9 export function oid(instance: NonNullable<any>): string;
11 export function oid(instance: any): string | undefined {
10 export function oid(instance: any): string | undefined {
12 if (isNull(instance))
11 if (isNull(instance))
13 return undefined;
12 return undefined;
14
13
15 if (_oid in instance)
14 if (_oid in instance)
16 return instance[_oid];
15 return instance[_oid];
17 else
16 else
18 return (instance[_oid] = "oid_" + (++_nextOid));
17 return (instance[_oid] = "oid_" + (++_nextOid));
19 }
18 }
20
19
20 const cancellationNone: ICancellation = {
21 isSupported(): boolean {
22 return false;
23 },
24
25 throwIfRequested(): void {
26 },
27
28 isRequested(): boolean {
29 return false;
30 },
31
32 register(_cb: (e: any) => void): IDestroyable {
33 return destroyed;
34 }
35 };
36
21 export function keys<T>(arg: T): (Extract<keyof T, string>)[] {
37 export function keys<T>(arg: T): (Extract<keyof T, string>)[] {
22 return isObject(arg) && arg ? Object.keys(arg) as (Extract<keyof T, string>)[] : [];
38 return isObject(arg) && arg ? Object.keys(arg) as (Extract<keyof T, string>)[] : [];
23 }
39 }
24
40
25 export function isKeyof<T>(k: string, target: T): k is Extract<keyof T, string> {
41 export function isKeyof<T>(k: string, target: T): k is Extract<keyof T, string> {
26 return target && typeof target === "object" && k in target;
42 return target && typeof target === "object" && k in target;
27 }
43 }
28
44
29 export function argumentNotNull(arg: any, name: string) {
45 export function argumentNotNull(arg: any, name: string) {
30 if (arg === null || arg === undefined)
46 if (arg === null || arg === undefined)
31 throw new Error("The argument " + name + " can't be null or undefined");
47 throw new Error("The argument " + name + " can't be null or undefined");
32 }
48 }
33
49
34 export function argumentNotEmptyString(arg: any, name: string) {
50 export function argumentNotEmptyString(arg: any, name: string) {
35 if (typeof (arg) !== "string" || !arg.length)
51 if (typeof (arg) !== "string" || !arg.length)
36 throw new Error("The argument '" + name + "' must be a not empty string");
52 throw new Error("The argument '" + name + "' must be a not empty string");
37 }
53 }
38
54
39 export function argumentNotEmptyArray(arg: any, name: string) {
55 export function argumentNotEmptyArray(arg: any, name: string) {
40 if (!(arg instanceof Array) || !arg.length)
56 if (!(arg instanceof Array) || !arg.length)
41 throw new Error("The argument '" + name + "' must be a not empty array");
57 throw new Error("The argument '" + name + "' must be a not empty array");
42 }
58 }
43
59
44 export function argumentOfType(arg: any, type: Constructor<{}>, name: string) {
60 export function argumentOfType(arg: any, type: Constructor<{}>, name: string) {
45 if (!(arg instanceof type))
61 if (!(arg instanceof type))
46 throw new Error("The argument '" + name + "' type doesn't match");
62 throw new Error("The argument '" + name + "' type doesn't match");
47 }
63 }
48
64
49 export function isObject(val: any): val is object {
65 export function isObject(val: any): val is object {
50 return typeof val === "object";
66 return typeof val === "object";
51 }
67 }
52
68
53 export function isNull(val: any): val is null | undefined {
69 export function isNull(val: any): val is null | undefined {
54 return (val === null || val === undefined);
70 return (val === null || val === undefined);
55 }
71 }
56
72
57 export type primitive = symbol | string | number | boolean | undefined | null;
73 export type primitive = symbol | string | number | boolean | undefined | null;
58
74
59 export function isPrimitive(val: any): val is primitive {
75 export function isPrimitive(val: any): val is primitive {
60 return (val === null || val === undefined || typeof (val) === "string" ||
76 return (val === null || val === undefined || typeof (val) === "string" ||
61 typeof (val) === "number" || typeof (val) === "boolean");
77 typeof (val) === "number" || typeof (val) === "boolean");
62 }
78 }
63
79
64 export function isInteger(val: any): val is number {
80 export function isInteger(val: any): val is number {
65 return parseInt(val, 10) === val;
81 return parseInt(val, 10) === val;
66 }
82 }
67
83
68 export function isNumber(val: any): val is number {
84 export function isNumber(val: any): val is number {
69 return parseFloat(val) === val;
85 return parseFloat(val) === val;
70 }
86 }
71
87
72 export function isString(val: any): val is string {
88 export function isString(val: any): val is string {
73 return typeof (val) === "string" || val instanceof String;
89 return typeof (val) === "string" || val instanceof String;
74 }
90 }
75
91
76 export function isPromise<T = any>(val: any): val is PromiseLike<T> {
92 export function isPromise<T = any>(val: any): val is PromiseLike<T> {
77 return val && typeof val.then === "function";
93 return val && typeof val.then === "function";
78 }
94 }
79
95
80 export function isCancellable(val: any): val is ICancellable {
96 export function isCancellable(val: any): val is ICancellable {
81 return val && typeof val.cancel === "function";
97 return val && typeof val.cancel === "function";
82 }
98 }
83
99
84 export function isNullOrEmptyString(val: any): val is ("" | null | undefined) {
100 export function isNullOrEmptyString(val: any): val is ("" | null | undefined) {
85 return (val === null || val === undefined ||
101 return (val === null || val === undefined ||
86 ((typeof (val) === "string" || val instanceof String) && val.length === 0));
102 ((typeof (val) === "string" || val instanceof String) && val.length === 0));
87 }
103 }
88
104
89 export function isNotEmptyArray<T = any>(arg: any): arg is T[] {
105 export function isNotEmptyArray<T = any>(arg: any): arg is T[] {
90 return (arg instanceof Array && arg.length > 0);
106 return (arg instanceof Array && arg.length > 0);
91 }
107 }
92
108
93 function _isStrictMode(this: any) {
109 function _isStrictMode(this: any) {
94 return !this;
110 return !this;
95 }
111 }
96
112
97 function _getNonStrictGlobal(this: any) {
113 function _getNonStrictGlobal(this: any) {
98 return this;
114 return this;
99 }
115 }
100
116
101 export function getGlobal() {
117 export function getGlobal() {
102 // in es3 we can't use indirect call to eval, since it will
118 // in es3 we can't use indirect call to eval, since it will
103 // be executed in the current call context.
119 // be executed in the current call context.
104 if (!_isStrictMode()) {
120 if (!_isStrictMode()) {
105 return _getNonStrictGlobal();
121 return _getNonStrictGlobal();
106 } else {
122 } else {
107 // tslint:disable-next-line:no-eval
123 // tslint:disable-next-line:no-eval
108 return eval.call(null, "this");
124 return eval.call(null, "this");
109 }
125 }
110 }
126 }
111
127
112 export function get(member: string, context?: object) {
128 export function get(member: string, context?: object) {
113 argumentNotEmptyString(member, "member");
129 argumentNotEmptyString(member, "member");
114 let that = context || getGlobal();
130 let that = context || getGlobal();
115 const parts = member.split(".");
131 const parts = member.split(".");
116 for (const m of parts) {
132 for (const m of parts) {
117 if (!m)
133 if (!m)
118 continue;
134 continue;
119 if (isNull(that = that[m]))
135 if (isNull(that = that[m]))
120 break;
136 break;
121 }
137 }
122 return that;
138 return that;
123 }
139 }
124
140
125 /**
141 /**
126 * ВыполняСт ΠΌΠ΅Ρ‚ΠΎΠ΄ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ элСмСнта массива, останавливаСтся, ΠΊΠΎΠ³Π΄Π°
142 * ВыполняСт ΠΌΠ΅Ρ‚ΠΎΠ΄ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ элСмСнта массива, останавливаСтся, ΠΊΠΎΠ³Π΄Π°
127 * Π»ΠΈΠ±ΠΎ достигнут ΠΊΠΎΠ½Π΅Ρ† массива, Π»ΠΈΠ±ΠΎ функция <c>cb</c> Π²Π΅Ρ€Π½ΡƒΠ»Π°
143 * Π»ΠΈΠ±ΠΎ достигнут ΠΊΠΎΠ½Π΅Ρ† массива, Π»ΠΈΠ±ΠΎ функция <c>cb</c> Π²Π΅Ρ€Π½ΡƒΠ»Π°
128 * Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
144 * Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
129 *
145 *
130 * @param {Array | Object} obj массив элСмСнтов для просмотра
146 * @param {Array | Object} obj массив элСмСнтов для просмотра
131 * @param {Function} cb функция, вызываСмая для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ элСмСнта
147 * @param {Function} cb функция, вызываСмая для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ элСмСнта
132 * @param {Object} thisArg Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ΠΎ Π² качСствС
148 * @param {Object} thisArg Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ΠΎ Π² качСствС
133 * <c>this</c> Π² <c>cb</c>.
149 * <c>this</c> Π² <c>cb</c>.
134 * @returns {void}
150 * @returns {void}
135 */
151 */
136 export function each<T>(obj: T, cb: <X extends keyof T>(v: NonNullable<T[X]>, k: X) => void): void;
152 export function each<T>(obj: T, cb: <X extends keyof T>(v: NonNullable<T[X]>, k: X) => void): void;
137 export function each<T>(array: T[], cb: (v: T, i: number) => void): void;
153 export function each<T>(array: T[], cb: (v: T, i: number) => void): void;
138 export function each(obj: any, cb: any, thisArg?: any): any;
154 export function each(obj: any, cb: any, thisArg?: any): any;
139 export function each(obj: any, cb: any, thisArg?: any) {
155 export function each(obj: any, cb: any, thisArg?: any) {
140 argumentNotNull(cb, "cb");
156 argumentNotNull(cb, "cb");
141 if (obj instanceof Array) {
157 if (obj instanceof Array) {
142 let v: any;
158 let v: any;
143 for (let i = 0; i < obj.length; i++) {
159 for (let i = 0; i < obj.length; i++) {
144 v = obj[i];
160 v = obj[i];
145 if (v !== undefined)
161 if (v !== undefined)
146 cb.call(thisArg, v, i);
162 cb.call(thisArg, v, i);
147 }
163 }
148 } else {
164 } else {
149 Object.keys(obj).forEach(k => obj[k] !== undefined && cb.call(thisArg, obj[k], k));
165 Object.keys(obj).forEach(k => obj[k] !== undefined && cb.call(thisArg, obj[k], k));
150 }
166 }
151 }
167 }
152
168
153 /** Copies property values from a source object to the destination and returns
169 /** Copies property values from a source object to the destination and returns
154 * the destination object.
170 * the destination object.
155 *
171 *
156 * @param dest The destination object into which properties from the source
172 * @param dest The destination object into which properties from the source
157 * object will be copied.
173 * object will be copied.
158 * @param source The source of values which will be copied to the destination
174 * @param source The source of values which will be copied to the destination
159 * object.
175 * object.
160 * @param template An optional parameter specifies which properties should be
176 * @param template An optional parameter specifies which properties should be
161 * copied from the source and how to map them to the destination. If the
177 * copied from the source and how to map them to the destination. If the
162 * template is an array it contains the list of property names to copy from the
178 * template is an array it contains the list of property names to copy from the
163 * source to the destination. In case of object the templates contains the map
179 * source to the destination. In case of object the templates contains the map
164 * where keys are property names in the source and the values are property
180 * where keys are property names in the source and the values are property
165 * names in the destination object. If the template isn't specified then the
181 * names in the destination object. If the template isn't specified then the
166 * own properties of the source are entirely copied to the destination.
182 * own properties of the source are entirely copied to the destination.
167 *
183 *
168 */
184 */
169 export function mixin<T extends object, S extends object>(dest: T, source: S, template?: (keyof S)[]): T & S;
185 export function mixin<T extends object, S extends object>(dest: T, source: S, template?: (keyof S)[]): T & S;
170 export function mixin<T extends object, S extends object, R extends object = T>(dest: T, source: S, template: { [p in keyof S]?: keyof R; }): T & R;
186 export function mixin<T extends object, S extends object, R extends object = T>(dest: T, source: S, template: { [p in keyof S]?: keyof R; }): T & R;
171 export function mixin<T extends object, S extends object>(dest: T, source: S, template?: any): any {
187 export function mixin<T extends object, S extends object>(dest: T, source: S, template?: any): any {
172 argumentNotNull(dest, "dest");
188 argumentNotNull(dest, "dest");
173 const _res: any = dest as any;
189 const _res: any = dest as any;
174
190
175 if (isPrimitive(source))
191 if (isPrimitive(source))
176 return _res;
192 return _res;
177
193
178 if (template instanceof Array) {
194 if (template instanceof Array) {
179 template.forEach(p => {
195 template.forEach(p => {
180 if (isKeyof(p, source))
196 if (isKeyof(p, source))
181 _res[p] = source[p];
197 _res[p] = source[p];
182 });
198 });
183 } else if (template) {
199 } else if (template) {
184 keys(source).forEach(p => {
200 keys(source).forEach(p => {
185 if (isKeyof(p, template))
201 if (isKeyof(p, template))
186 _res[template[p]] = source[p];
202 _res[template[p]] = source[p];
187 });
203 });
188 } else {
204 } else {
189 keys(source).forEach(p => _res[p] = source[p]);
205 keys(source).forEach(p => _res[p] = source[p]);
190 }
206 }
191
207
192 return _res;
208 return _res;
193 }
209 }
194
210
195 /** Wraps the specified function to emulate an asynchronous execution.
211 /** Wraps the specified function to emulate an asynchronous execution.
196 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
212 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
197 * @param{Function|String} fn [Required] Function wich will be wrapped.
213 * @param{Function|String} fn [Required] Function wich will be wrapped.
198 */
214 */
199 export function async<T, F extends (...args: any[]) => T | PromiseLike<T>>(
215 export function async<T, F extends (...args: any[]) => T | PromiseLike<T>>(
200 fn: F,
216 fn: F,
201 thisArg?: ThisParameterType<F>
217 thisArg?: ThisParameterType<F>
202 ): (...args: Parameters<F>) => PromiseLike<T>;
218 ): (...args: Parameters<F>) => PromiseLike<T>;
203 export function async<T, M extends string, O extends { [m in M]?: (...args: any[]) => T | PromiseLike<T> }>(
219 export function async<T, M extends string, O extends { [m in M]?: (...args: any[]) => T | PromiseLike<T> }>(
204 fn: M,
220 fn: M,
205 thisArg: O
221 thisArg: O
206 ): (...args: Parameters<NonNullable<O[M]>>) => PromiseLike<T>;
222 ): (...args: Parameters<NonNullable<O[M]>>) => PromiseLike<T>;
207 export function async(_fn: any, thisArg: any): (...args: any[]) => PromiseLike<any> {
223 export function async(_fn: any, thisArg: any): (...args: any[]) => PromiseLike<any> {
208 let fn = _fn;
224 let fn = _fn;
209
225
210 if (arguments.length === 2 && !(fn instanceof Function))
226 if (arguments.length === 2 && !(fn instanceof Function))
211 fn = thisArg[fn];
227 fn = thisArg[fn];
212
228
213 if (fn == null)
229 if (fn == null)
214 throw new Error("The function must be specified");
230 throw new Error("The function must be specified");
215
231
216 function wrapresult(x: any, e?: any): PromiseLike<any> {
232 function wrapresult(x: any, e?: any): PromiseLike<any> {
217 if (e) {
233 if (e) {
218 return {
234 return {
219 then(cb, eb) {
235 then(cb, eb) {
220 try {
236 try {
221 return eb ? wrapresult(eb(e)) : this;
237 return eb ? wrapresult(eb(e)) : this;
222 } catch (e2) {
238 } catch (e2) {
223 return wrapresult(null, e2);
239 return wrapresult(null, e2);
224 }
240 }
225 }
241 }
226 };
242 };
227 } else {
243 } else {
228 if (x && x.then)
244 if (x && x.then)
229 return x;
245 return x;
230 return {
246 return {
231 then(cb) {
247 then(cb) {
232 try {
248 try {
233 return cb ? wrapresult(cb(x)) : this;
249 return cb ? wrapresult(cb(x)) : this;
234 } catch (e2) {
250 } catch (e2) {
235 return wrapresult(e2);
251 return wrapresult(e2);
236 }
252 }
237 }
253 }
238 };
254 };
239 }
255 }
240 }
256 }
241
257
242 return (...args) => {
258 return (...args) => {
243 try {
259 try {
244 return wrapresult(fn.apply(thisArg, args));
260 return wrapresult(fn.apply(thisArg, args));
245 } catch (e) {
261 } catch (e) {
246 return wrapresult(null, e);
262 return wrapresult(null, e);
247 }
263 }
248 };
264 };
249 }
265 }
250
266
251 export function delegate<T extends object, F extends (this: T, ...args: any[]) => any>(
267 export function delegate<T extends object, F extends (this: T, ...args: any[]) => any>(
252 target: T,
268 target: T,
253 method: F
269 method: F
254 ): OmitThisParameter<F>;
270 ): OmitThisParameter<F>;
255 export function delegate<M extends string, T extends { [m in M]?: (...args: any[]) => any; }>(
271 export function delegate<M extends string, T extends { [m in M]?: (...args: any[]) => any; }>(
256 target: T,
272 target: T,
257 method: M
273 method: M
258 ): OmitThisParameter<T[M]>;
274 ): OmitThisParameter<T[M]>;
259 export function delegate(target: any, _method: any): (...args: any[]) => any {
275 export function delegate(target: any, _method: any): (...args: any[]) => any {
260 let method: any;
276 let method: any;
261 if (!(_method instanceof Function)) {
277 if (!(_method instanceof Function)) {
262 argumentNotNull(target, "target");
278 argumentNotNull(target, "target");
263 method = target[_method];
279 method = target[_method];
264 if (!(method instanceof Function))
280 if (!(method instanceof Function))
265 throw new Error("'method' argument must be a Function or a method name");
281 throw new Error("'method' argument must be a Function or a method name");
266 } else {
282 } else {
267 method = _method;
283 method = _method;
268 }
284 }
269
285
270 return (...args) => {
286 return (...args) => {
271 return method.apply(target, args);
287 return method.apply(target, args);
272 };
288 };
273 }
289 }
274
290
275 export function delay(timeMs: number, ct = Cancellation.none) {
291 export function delay(timeMs: number, ct = cancellationNone) {
276 ct.throwIfRequested();
292 ct.throwIfRequested();
277 return new Promise((resolve, reject) => {
293 return new Promise((resolve, reject) => {
278 const h = ct.register(e => {
294 const h = ct.register(e => {
279 clearTimeout(id);
295 clearTimeout(id);
280 reject(e);
296 reject(e);
281 // we don't nedd to unregister h, since ct is already disposed
297 // we don't nedd to unregister h, since ct is already disposed
282 });
298 });
283 const id = setTimeout(() => {
299 const id = setTimeout(() => {
284 h.destroy();
300 h.destroy();
285 resolve();
301 resolve();
286 }, timeMs);
302 }, timeMs);
287
303
288 });
304 });
289 }
305 }
290
306
291 /** Returns resolved promise, awaiting this method will cause the asynchronous
307 /** Returns resolved promise, awaiting this method will cause the asynchronous
292 * completion of the rest of the code.
308 * completion of the rest of the code.
293 */
309 */
294 export function fork() {
310 export function fork() {
295 return Promise.resolve();
311 return Promise.resolve();
296 }
312 }
297
313
298 /** Always throws Error, can be used as a stub for the methods which should be
314 /** Always throws Error, can be used as a stub for the methods which should be
299 * assigned later and are required to be not null.
315 * assigned later and are required to be not null.
300 */
316 */
301 export function notImplemented(): never {
317 export function notImplemented(): never {
302 throw new Error("Not implemeted");
318 throw new Error("Not implemeted");
303 }
319 }
304 /**
320 /**
305 * Iterates over the specified array of items and calls the callback `cb`, if
321 * Iterates over the specified array of items and calls the callback `cb`, if
306 * the result of the callback is a promise the next item from the array will be
322 * the result of the callback is a promise the next item from the array will be
307 * proceeded after the promise is resolved.
323 * proceeded after the promise is resolved.
308 *
324 *
309 */
325 */
310 export function pmap<T, T2>(
326 export function pmap<T, T2>(
311 items: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
327 items: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
312 cb: (item: T, i: number) => T2 | PromiseLike<T2>
328 cb: (item: T, i: number) => T2 | PromiseLike<T2>
313 ): T2[] | PromiseLike<T2[]> {
329 ): T2[] | PromiseLike<T2[]> {
314 argumentNotNull(cb, "cb");
330 argumentNotNull(cb, "cb");
315
331
316 if (isPromise(items)) {
332 if (isPromise(items)) {
317 return items.then(data => pmap(data, cb));
333 return items.then(data => pmap(data, cb));
318 } else {
334 } else {
319
335
320 if (isNull(items) || !items.length)
336 if (isNull(items) || !items.length)
321 return [];
337 return [];
322
338
323 let i = 0;
339 let i = 0;
324 const result = new Array<T2>();
340 const result = new Array<T2>();
325
341
326 const next = (): any => {
342 const next = (): any => {
327 while (i < items.length) {
343 while (i < items.length) {
328 const r = cb(items[i], i);
344 const r = cb(items[i], i);
329 const ri = i;
345 const ri = i;
330 i++;
346 i++;
331 if (isPromise(r)) {
347 if (isPromise(r)) {
332 return r.then(x => {
348 return r.then(x => {
333 result[ri] = x;
349 result[ri] = x;
334 return next();
350 return next();
335 });
351 });
336 } else {
352 } else {
337 result[ri] = r;
353 result[ri] = r;
338 }
354 }
339 }
355 }
340 return result;
356 return result;
341 };
357 };
342
358
343 return next();
359 return next();
344 }
360 }
345 }
361 }
346
362
347 export function pfor<T>(
363 export function pfor<T>(
348 items: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
364 items: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
349 cb: (item: T, i: number) => any
365 cb: (item: T, i: number) => any
350 ): void | PromiseLike<void> {
366 ): void | PromiseLike<void> {
351 argumentNotNull(cb, "cb");
367 argumentNotNull(cb, "cb");
352
368
353 if (isPromise(items)) {
369 if (isPromise(items)) {
354 return items.then(data => pfor(data, cb));
370 return items.then(data => pfor(data, cb));
355 } else {
371 } else {
356 if (isNull(items) || !items.length)
372 if (isNull(items) || !items.length)
357 return;
373 return;
358
374
359 let i = 0;
375 let i = 0;
360
376
361 const next = (): any => {
377 const next = (): any => {
362 while (i < items.length) {
378 while (i < items.length) {
363 const r = cb(items[i], i);
379 const r = cb(items[i], i);
364 i++;
380 i++;
365 if (isPromise(r))
381 if (isPromise(r))
366 return r.then(next);
382 return r.then(next);
367 }
383 }
368 };
384 };
369
385
370 return next();
386 return next();
371 }
387 }
372 }
388 }
373
389
374 export function first<T>(sequence: ArrayLike<T>): T;
390 export function first<T>(sequence: ArrayLike<T>): T;
375 export function first<T>(sequence: PromiseLike<ArrayLike<T>>): PromiseLike<T>;
391 export function first<T>(sequence: PromiseLike<ArrayLike<T>>): PromiseLike<T>;
376 export function first<T>(
392 export function first<T>(
377 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
393 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
378 cb?: (x: T) => void,
394 cb?: (x: T) => void,
379 err?: (x: Error) => void
395 err?: (x: Error) => void
380 ): void;
396 ): void;
381 /**
397 /**
382 * Π’Ρ‹Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт ΠΈΠ· ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, ΠΈΠ»ΠΈ обСщания, Ссли Π²
398 * Π’Ρ‹Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт ΠΈΠ· ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, ΠΈΠ»ΠΈ обСщания, Ссли Π²
383 * качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ½ΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ массив.
399 * качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ½ΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ массив.
384 *
400 *
385 * @param {Function} cb ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, Π΅ΠΌΡƒ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ
401 * @param {Function} cb ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, Π΅ΠΌΡƒ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ
386 * элСмСнт ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π² случаС успСха
402 * элСмСнт ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π² случаС успСха
387 * @param {Function} err ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, Ссли массив пустой, Π»ΠΈΠ±ΠΎ
403 * @param {Function} err ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, Ссли массив пустой, Π»ΠΈΠ±ΠΎ
388 * нС массив
404 * нС массив
389 *
405 *
390 * @remarks Если Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π½ΠΈ cb Π½ΠΈ err, Ρ‚ΠΎΠ³Π΄Π° функция Π²Π΅Ρ€Π½Π΅Ρ‚ Π»ΠΈΠ±ΠΎ
406 * @remarks Если Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π½ΠΈ cb Π½ΠΈ err, Ρ‚ΠΎΠ³Π΄Π° функция Π²Π΅Ρ€Π½Π΅Ρ‚ Π»ΠΈΠ±ΠΎ
391 * ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, Π»ΠΈΠ±ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт.
407 * ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, Π»ΠΈΠ±ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт.
392 * @async
408 * @async
393 */
409 */
394 export function first<T>(
410 export function first<T>(
395 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
411 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
396 cb?: (x: T) => void,
412 cb?: (x: T) => void,
397 err?: (x: Error) => void
413 err?: (x: Error) => void
398 ) {
414 ) {
399 if (isPromise(sequence)) {
415 if (isPromise(sequence)) {
400 return sequence.then(res => first(res, cb as any /* force to pass undefined cb */, err));
416 return sequence.then(res => first(res, cb as any /* force to pass undefined cb */, err));
401 } else if (sequence && "length" in sequence) {
417 } else if (sequence && "length" in sequence) {
402 if (sequence.length === 0) {
418 if (sequence.length === 0) {
403 if (err)
419 if (err)
404 return err(new Error("The sequence is empty"));
420 return err(new Error("The sequence is empty"));
405 else
421 else
406 throw new Error("The sequence is empty");
422 throw new Error("The sequence is empty");
407 } else if (cb) {
423 } else if (cb) {
408 return cb(sequence[0]);
424 return cb(sequence[0]);
409 } else {
425 } else {
410 return sequence[0];
426 return sequence[0];
411 }
427 }
412 } else {
428 } else {
413 if (err)
429 if (err)
414 return err(new Error("The sequence is required"));
430 return err(new Error("The sequence is required"));
415 else
431 else
416 throw new Error("The sequence is required");
432 throw new Error("The sequence is required");
417 }
433 }
418 }
434 }
419
435
420 export function firstWhere<T>(
436 export function firstWhere<T>(
421 sequence: ArrayLike<T>,
437 sequence: ArrayLike<T>,
422 predicate: (x: T) => boolean
438 predicate: (x: T) => boolean
423 ): T;
439 ): T;
424 export function firstWhere<T>(
440 export function firstWhere<T>(
425 sequence: PromiseLike<ArrayLike<T>>,
441 sequence: PromiseLike<ArrayLike<T>>,
426 predicate: (x: T) => boolean
442 predicate: (x: T) => boolean
427 ): PromiseLike<T>;
443 ): PromiseLike<T>;
428 export function firstWhere<T>(
444 export function firstWhere<T>(
429 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
445 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
430 predicate: (x: T) => boolean,
446 predicate: (x: T) => boolean,
431 cb: (x: T) => void,
447 cb: (x: T) => void,
432 err?: (x: Error) => void
448 err?: (x: Error) => void
433 ): void;
449 ): void;
434
450
435 export function firstWhere<T>(
451 export function firstWhere<T>(
436 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
452 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
437 predicate?: (x: T) => boolean,
453 predicate?: (x: T) => boolean,
438 cb?: (x: T) => any,
454 cb?: (x: T) => any,
439 err?: (x: Error) => any
455 err?: (x: Error) => any
440 ) {
456 ) {
441 if (isPromise(sequence)) {
457 if (isPromise(sequence)) {
442 return sequence.then(res => firstWhere(
458 return sequence.then(res => firstWhere(
443 res,
459 res,
444 predicate as any /* force to pass undefined predicate */,
460 predicate as any /* force to pass undefined predicate */,
445 cb as any /* force to pass undefined cb */,
461 cb as any /* force to pass undefined cb */,
446 err)
462 err)
447 );
463 );
448 } else if (sequence && "length" in sequence) {
464 } else if (sequence && "length" in sequence) {
449 if (sequence.length === 0) {
465 if (sequence.length === 0) {
450 if (err)
466 if (err)
451 err(new Error("The sequence is empty"));
467 err(new Error("The sequence is empty"));
452 else
468 else
453 throw new Error("The sequence is empty");
469 throw new Error("The sequence is empty");
454 } else {
470 } else {
455 if (!predicate) {
471 if (!predicate) {
456 return cb ? cb(sequence[0]) && void (0) : sequence[0];
472 return cb ? cb(sequence[0]) && void (0) : sequence[0];
457 } else {
473 } else {
458 for (let i = 0; i < sequence.length; i++) {
474 for (let i = 0; i < sequence.length; i++) {
459 const v = sequence[i];
475 const v = sequence[i];
460 if (predicate(v))
476 if (predicate(v))
461 return cb ? cb(v) : v;
477 return cb ? cb(v) : v;
462 }
478 }
463 if (err)
479 if (err)
464 err(new Error("The sequence doesn't contain matching items"));
480 err(new Error("The sequence doesn't contain matching items"));
465 else
481 else
466 throw new Error("The sequence doesn't contain matching items");
482 throw new Error("The sequence doesn't contain matching items");
467 }
483 }
468 }
484 }
469 } else {
485 } else {
470 if (err)
486 if (err)
471 err(new Error("The sequence is required"));
487 err(new Error("The sequence is required"));
472 else
488 else
473 throw new Error("The sequence is required");
489 throw new Error("The sequence is required");
474 }
490 }
475 }
491 }
476
492
477 export function isDestroyable(d: any): d is IDestroyable {
493 export function isDestroyable(d: any): d is IDestroyable {
478 if (d && "destroy" in d && typeof (destroy) === "function")
494 if (d && "destroy" in d && typeof (destroy) === "function")
479 return true;
495 return true;
480 return false;
496 return false;
481 }
497 }
482
498
483 export function destroy(d: any) {
499 export function destroy(d: any) {
484 if (d && "destroy" in d)
500 if (d && "destroy" in d)
485 d.destroy();
501 d.destroy();
486 }
502 }
487
503
488 /**
504 /**
489 * Used to mark that the async operation isn't awaited intentionally.
505 * Used to mark that the async operation isn't awaited intentionally.
490 * @param p The promise which represents the async operation.
506 * @param p The promise which represents the async operation.
491 */
507 */
492 export function nowait(p: Promise<any>) {
508 export function nowait(p: Promise<any>) {
493 }
509 }
494
510
495 /** represents already destroyed object.
511 /** represents already destroyed object.
496 */
512 */
497 export const destroyed = {
513 export const destroyed = {
498 /** Calling to this method doesn't affect anything, noop.
514 /** Calling to this method doesn't affect anything, noop.
499 */
515 */
500 destroy() {
516 destroy() {
501 }
517 }
502 };
518 };
General Comments 0
You need to be logged in to leave comments. Login now