@idlebox/common 1.5.21 → 1.5.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/autoindex.generated.d.ts +0 -2
- package/lib/autoindex.generated.d.ts.map +1 -1
- package/lib/autoindex.generated.js +1 -8
- package/lib/autoindex.generated.js.map +1 -1
- package/lib/debugging/inspect.d.ts.map +1 -1
- package/lib/debugging/inspect.js +2 -1
- package/lib/debugging/inspect.js.map +1 -1
- package/lib/error/pretty.nodejs.d.ts.map +1 -1
- package/lib/error/pretty.nodejs.js +4 -1
- package/lib/error/pretty.nodejs.js.map +1 -1
- package/lib/error/stack-parser.v8.js +2 -2
- package/lib/error/stack-parser.v8.js.map +1 -1
- package/lib/lifecycle/dispose/disposable.d.ts +4 -1
- package/lib/lifecycle/dispose/disposable.d.ts.map +1 -1
- package/lib/lifecycle/dispose/disposable.js +58 -27
- package/lib/lifecycle/dispose/disposable.js.map +1 -1
- package/lib/lifecycle/event/event.d.ts +26 -3
- package/lib/lifecycle/event/event.d.ts.map +1 -1
- package/lib/lifecycle/event/event.js +83 -34
- package/lib/lifecycle/event/event.js.map +1 -1
- package/lib/map-and-set/required-map.d.ts.map +1 -1
- package/lib/map-and-set/required-map.js +8 -0
- package/lib/map-and-set/required-map.js.map +1 -1
- package/lib/promise/deferred-promise.d.ts +1 -0
- package/lib/promise/deferred-promise.d.ts.map +1 -1
- package/lib/promise/deferred-promise.js +5 -5
- package/lib/promise/deferred-promise.js.map +1 -1
- package/lib/re-export.d.ts.map +1 -1
- package/lib/re-export.js +0 -1
- package/lib/re-export.js.map +1 -1
- package/lib/schedule/extendable-timer.d.ts +1 -1
- package/lib/schedule/extendable-timer.d.ts.map +1 -1
- package/lib/schedule/extendable-timer.js.map +1 -1
- package/lib/schedule/timeout.d.ts +1 -1
- package/lib/schedule/timeout.d.ts.map +1 -1
- package/lib/schedule/timeout.js +6 -9
- package/lib/schedule/timeout.js.map +1 -1
- package/package.json +9 -12
- package/src/autoindex.generated.ts +1 -12
- package/src/debugging/inspect.ts +2 -1
- package/src/error/pretty.nodejs.ts +5 -1
- package/src/error/stack-parser.v8.ts +2 -2
- package/src/lifecycle/dispose/disposable.ts +75 -29
- package/src/lifecycle/event/event.ts +81 -34
- package/src/map-and-set/required-map.ts +10 -0
- package/src/promise/deferred-promise.ts +5 -6
- package/src/re-export.ts +0 -1
- package/src/schedule/extendable-timer.ts +1 -2
- package/src/schedule/timeout.ts +8 -4
- package/lib/schedule/local-type.d.ts +0 -3
- package/lib/schedule/local-type.d.ts.map +0 -1
- package/lib/schedule/local-type.js +0 -2
- package/lib/schedule/local-type.js.map +0 -1
- package/src/schedule/local-type.ts +0 -2
- package/src/string/concatType.generator.ts +0 -31
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { defineInspectMethod } from '../../debugging/inspect.js';
|
|
2
2
|
import type { MaybeNamed } from '../../debugging/object-with-name.js';
|
|
3
|
+
import { convertCaughtError } from '../../error/convert-unknown.js';
|
|
4
|
+
import { prettyPrintError } from '../../error/pretty.nodejs.js';
|
|
3
5
|
import { createStackTraceHolder, type StackTraceHolder } from '../../error/stack-trace.js';
|
|
4
|
-
import { definePublicConstant } from '../../object/definePublicConstant.js';
|
|
5
6
|
import { isPromiseLike } from '../../promise/is-promise.js';
|
|
6
7
|
import { Emitter } from '../event/event.js';
|
|
7
8
|
import type { EventRegister } from '../event/type.js';
|
|
@@ -39,6 +40,22 @@ export interface IAsyncDisposable extends MaybeNamed {
|
|
|
39
40
|
type _Type<Async extends boolean> = Async extends true ? IAsyncDisposable : IDisposable;
|
|
40
41
|
type _RType<Async extends boolean> = Async extends true ? Promise<void> : void;
|
|
41
42
|
|
|
43
|
+
interface IDisposeState<Async extends boolean> {
|
|
44
|
+
/**
|
|
45
|
+
* 存在stack说明dispose已经开始(可能已经完成)
|
|
46
|
+
*/
|
|
47
|
+
trace?: StackTraceHolder;
|
|
48
|
+
finished: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* 同步的是undefined,异步的是Promise
|
|
51
|
+
*/
|
|
52
|
+
result?: _RType<Async>;
|
|
53
|
+
/**
|
|
54
|
+
* 只有同步的用到,每次调用始终抛出相同错误,异步通过promise保存状态
|
|
55
|
+
*/
|
|
56
|
+
error?: Error;
|
|
57
|
+
}
|
|
58
|
+
|
|
42
59
|
/**
|
|
43
60
|
* 增强型Disposable
|
|
44
61
|
*/
|
|
@@ -74,11 +91,11 @@ export abstract class AbstractEnhancedDisposable<Async extends boolean> implemen
|
|
|
74
91
|
return `[Function debug]`;
|
|
75
92
|
});
|
|
76
93
|
|
|
77
|
-
this._onDisposeError = new Emitter<Error>(`${this.displayName}:errorEvent
|
|
94
|
+
this._onDisposeError = new Emitter<Error>(`${this.displayName}:errorEvent`, Emitter.EAction.PrintIgnore);
|
|
78
95
|
this.onDisposeError = this._onDisposeError.register;
|
|
79
|
-
this._onBeforeDispose = new Emitter<void>(`${this.displayName}:beforeEvent
|
|
96
|
+
this._onBeforeDispose = new Emitter<void>(`${this.displayName}:beforeEvent`, Emitter.EAction.PrintIgnore);
|
|
80
97
|
this.onBeforeDispose = this._onBeforeDispose.register;
|
|
81
|
-
this._onPostDispose = new Emitter<void>(`${this.displayName}:postEvent
|
|
98
|
+
this._onPostDispose = new Emitter<void>(`${this.displayName}:postEvent`, Emitter.EAction.PrintIgnore);
|
|
82
99
|
this.onPostDispose = this._onPostDispose.register;
|
|
83
100
|
}
|
|
84
101
|
|
|
@@ -86,8 +103,8 @@ export abstract class AbstractEnhancedDisposable<Async extends boolean> implemen
|
|
|
86
103
|
* @throws if already disposed
|
|
87
104
|
*/
|
|
88
105
|
public assertNotDisposed() {
|
|
89
|
-
if (this.
|
|
90
|
-
throw new DuplicateDisposedError(this, this.
|
|
106
|
+
if (this.__dispose_state.trace) {
|
|
107
|
+
throw new DuplicateDisposedError(this, this.__dispose_state.trace);
|
|
91
108
|
}
|
|
92
109
|
}
|
|
93
110
|
|
|
@@ -103,6 +120,7 @@ export abstract class AbstractEnhancedDisposable<Async extends boolean> implemen
|
|
|
103
120
|
this._disposables.unshift(fromNativeDisposable(d));
|
|
104
121
|
if (autoDereference) {
|
|
105
122
|
(d as IBackReferenceDisposableEvent).onBeforeDispose(() => {
|
|
123
|
+
if (this.disposing || this.disposed) return;
|
|
106
124
|
this._unregister(d);
|
|
107
125
|
});
|
|
108
126
|
}
|
|
@@ -122,60 +140,88 @@ export abstract class AbstractEnhancedDisposable<Async extends boolean> implemen
|
|
|
122
140
|
return rmOk;
|
|
123
141
|
}
|
|
124
142
|
|
|
125
|
-
private
|
|
126
|
-
trace: StackTraceHolder;
|
|
127
|
-
result: _RType<Async>;
|
|
128
|
-
};
|
|
143
|
+
private __dispose_state: IDisposeState<Async> = { finished: false };
|
|
129
144
|
public get disposed() {
|
|
130
|
-
return
|
|
145
|
+
return this.__dispose_state.finished;
|
|
131
146
|
}
|
|
132
147
|
|
|
148
|
+
/**
|
|
149
|
+
* 正在dispose中(已开始但未完成)
|
|
150
|
+
*/
|
|
133
151
|
public get disposing() {
|
|
134
|
-
return this.
|
|
152
|
+
return !this.__dispose_state.finished && !!this.__dispose_state.trace;
|
|
135
153
|
}
|
|
136
154
|
|
|
137
155
|
/**
|
|
138
156
|
* 释放相关资源
|
|
139
157
|
*/
|
|
140
158
|
public dispose(): _RType<Async> {
|
|
141
|
-
if (this.
|
|
142
|
-
|
|
159
|
+
if (this.__dispose_state.trace) {
|
|
160
|
+
// 释放已开始或已结束
|
|
161
|
+
if (this.duplicateDispose === DuplicateDisposeAction.Allow) {
|
|
162
|
+
if (this.__dispose_state.error) {
|
|
163
|
+
throw this.__dispose_state.error;
|
|
164
|
+
} else {
|
|
165
|
+
/**
|
|
166
|
+
* biome-ignore lint/style/noNonNullAssertion: 完全无需考虑
|
|
167
|
+
*
|
|
168
|
+
* 异步dispose的同步部分,重复调用dispose,会返回undefined而非Promise
|
|
169
|
+
* 但这正好是希望的,否则死锁了
|
|
170
|
+
*/
|
|
171
|
+
return this.__dispose_state.result!;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
143
174
|
|
|
144
|
-
const dupErr = new DuplicateDisposedError(this, this.
|
|
175
|
+
const dupErr = new DuplicateDisposedError(this, this.__dispose_state.trace);
|
|
145
176
|
dupErr.consoleWarning();
|
|
146
177
|
if (this.duplicateDispose === DuplicateDisposeAction.Disable) {
|
|
147
178
|
throw dupErr;
|
|
148
179
|
} else {
|
|
149
|
-
return this.
|
|
180
|
+
return this.__dispose_state.result as any;
|
|
150
181
|
}
|
|
182
|
+
// never
|
|
151
183
|
}
|
|
152
|
-
this._onBeforeDispose.fireNoError();
|
|
153
|
-
this._onBeforeDispose.dispose();
|
|
154
|
-
const trace = createStackTraceHolder('disposed', this.dispose);
|
|
155
184
|
|
|
156
185
|
const cleanup = () => {
|
|
157
|
-
|
|
158
|
-
// 记录 disposed 状态,顺便也记录调用栈
|
|
159
|
-
trace: trace,
|
|
160
|
-
result: r,
|
|
161
|
-
});
|
|
186
|
+
this.__dispose_state.finished = true;
|
|
162
187
|
|
|
163
188
|
Object.assign(this, { _disposables: null });
|
|
164
|
-
this._onPostDispose.
|
|
189
|
+
this._onPostDispose.fire();
|
|
165
190
|
this._onPostDispose.dispose();
|
|
191
|
+
|
|
166
192
|
this._onDisposeError.dispose();
|
|
167
193
|
};
|
|
168
194
|
|
|
169
|
-
|
|
195
|
+
// 第一时间设置trace
|
|
196
|
+
this.__dispose_state.trace = createStackTraceHolder('disposed', this.dispose);
|
|
197
|
+
|
|
198
|
+
this._onBeforeDispose.fire();
|
|
199
|
+
this._onBeforeDispose.dispose();
|
|
200
|
+
|
|
170
201
|
try {
|
|
171
|
-
|
|
202
|
+
this.__dispose_state.result = this._dispose(this._disposables);
|
|
172
203
|
} catch (e) {
|
|
204
|
+
// 同步错误处理
|
|
205
|
+
const err = convertCaughtError(e);
|
|
206
|
+
this.__dispose_state.error = err;
|
|
207
|
+
this._onDisposeError.fire(err);
|
|
208
|
+
if (this._onDisposeError.listenerCount() === 0) {
|
|
209
|
+
prettyPrintError('unhandled sync dispose error', err);
|
|
210
|
+
}
|
|
173
211
|
cleanup();
|
|
174
|
-
throw
|
|
212
|
+
throw this.__dispose_state.error;
|
|
175
213
|
}
|
|
176
214
|
|
|
215
|
+
const r = this.__dispose_state.result;
|
|
177
216
|
if (isPromiseLike(r)) {
|
|
178
|
-
|
|
217
|
+
// 异步错误处理
|
|
218
|
+
r.catch((e) => {
|
|
219
|
+
e = convertCaughtError(e);
|
|
220
|
+
this._onDisposeError.fire(e);
|
|
221
|
+
if (this._onDisposeError.listenerCount() === 0) {
|
|
222
|
+
prettyPrintError('unhandled async dispose error', e);
|
|
223
|
+
}
|
|
224
|
+
}).finally(cleanup);
|
|
179
225
|
} else {
|
|
180
226
|
cleanup();
|
|
181
227
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Exit } from '@idlebox/errors';
|
|
2
1
|
import { defineInspectMethod, inspectSymbol } from '../../debugging/inspect.js';
|
|
3
2
|
import { nameObject, objectName } from '../../debugging/object-with-name.js';
|
|
3
|
+
import { convertCaughtError } from '../../error/convert-unknown.js';
|
|
4
|
+
import { prettyPrintError } from '../../error/pretty.nodejs.js';
|
|
4
5
|
import { createStackTraceHolder } from '../../error/stack-trace.js';
|
|
5
6
|
import { functionToDisposable } from '../dispose/bridges/function.js';
|
|
6
7
|
import type { IDisposable } from '../dispose/disposable.js';
|
|
@@ -9,15 +10,27 @@ import type { EventHandler, EventRegister, IEventEmitter } from './type.js';
|
|
|
9
10
|
|
|
10
11
|
const anonymousName = 'AnonymousEmitter';
|
|
11
12
|
|
|
13
|
+
enum FireErrorAction {
|
|
14
|
+
Throw = 0,
|
|
15
|
+
Delay = 1,
|
|
16
|
+
Ignore = 2,
|
|
17
|
+
PrintIgnore = 3,
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
/**
|
|
13
21
|
* @public
|
|
14
22
|
*/
|
|
15
23
|
export class Emitter<T = unknown> implements IEventEmitter<T> {
|
|
16
|
-
protected _callbacks
|
|
24
|
+
protected readonly _callbacks: (EventHandler<T> | undefined)[] = [];
|
|
17
25
|
private executing = false;
|
|
18
26
|
private _something_change_during_call = false;
|
|
19
27
|
|
|
20
|
-
|
|
28
|
+
static readonly EAction = FireErrorAction;
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
public readonly displayName: string = anonymousName,
|
|
32
|
+
private readonly onErrorDefault: FireErrorAction = FireErrorAction.Throw,
|
|
33
|
+
) {
|
|
21
34
|
this.handle = Object.defineProperties(this.handle.bind(this), {
|
|
22
35
|
once: {
|
|
23
36
|
get: () => this.once.bind(this),
|
|
@@ -35,17 +48,69 @@ export class Emitter<T = unknown> implements IEventEmitter<T> {
|
|
|
35
48
|
}
|
|
36
49
|
|
|
37
50
|
public listenerCount() {
|
|
38
|
-
return this._callbacks
|
|
51
|
+
return this._callbacks.length;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private __fireThrow(data: T) {
|
|
55
|
+
for (const callback of this._callbacks) {
|
|
56
|
+
callback?.(data);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
private __fireDelay(data: T) {
|
|
60
|
+
const errors: Error[] = [];
|
|
61
|
+
for (const callback of this._callbacks) {
|
|
62
|
+
try {
|
|
63
|
+
callback?.(data);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
errors.push(convertCaughtError(e));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return errors;
|
|
69
|
+
}
|
|
70
|
+
private __fireIgnore(data: T) {
|
|
71
|
+
for (const callback of this._callbacks) {
|
|
72
|
+
try {
|
|
73
|
+
callback?.(data);
|
|
74
|
+
} catch {}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
private __firePrintIgnore(data: T) {
|
|
78
|
+
for (const callback of this._callbacks) {
|
|
79
|
+
try {
|
|
80
|
+
callback?.(data);
|
|
81
|
+
} catch (e) {
|
|
82
|
+
const ee = convertCaughtError(e);
|
|
83
|
+
prettyPrintError('error while handling event', ee);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
39
86
|
}
|
|
40
87
|
|
|
41
|
-
|
|
88
|
+
/**
|
|
89
|
+
* @param data
|
|
90
|
+
* @param error {Emitter.EAction} 如何处理错误
|
|
91
|
+
* - Throw: 默认行为,遇到错误立即抛出,后续监听器不再被调用
|
|
92
|
+
* - Delay: 等所有监听器都调用完后,如果有错误则抛出AggregateError,包含所有错误
|
|
93
|
+
* - Ignore: 忽略所有错误,继续调用全部监听器
|
|
94
|
+
* - PrintIgnore: 忽略所有错误,但打印错误信息
|
|
95
|
+
* @returns
|
|
96
|
+
*/
|
|
97
|
+
public fire(data: T, error = this.onErrorDefault) {
|
|
42
98
|
this.requireNotExecuting();
|
|
43
|
-
if (!this._callbacks) return;
|
|
99
|
+
if (!this._callbacks.length) return;
|
|
44
100
|
|
|
45
101
|
this.executing = true;
|
|
46
102
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
103
|
+
if (error === FireErrorAction.Throw) {
|
|
104
|
+
this.__fireThrow(data);
|
|
105
|
+
} else if (error === FireErrorAction.Delay) {
|
|
106
|
+
const errors = this.__fireDelay(data);
|
|
107
|
+
if (errors.length) {
|
|
108
|
+
throw new AggregateError(errors, 'multiple errors while handling event');
|
|
109
|
+
}
|
|
110
|
+
} else if (error === FireErrorAction.Ignore) {
|
|
111
|
+
this.__fireIgnore(data);
|
|
112
|
+
} else if (error === FireErrorAction.PrintIgnore) {
|
|
113
|
+
this.__firePrintIgnore(data);
|
|
49
114
|
}
|
|
50
115
|
} finally {
|
|
51
116
|
this.executing = false;
|
|
@@ -55,25 +120,9 @@ export class Emitter<T = unknown> implements IEventEmitter<T> {
|
|
|
55
120
|
}
|
|
56
121
|
}
|
|
57
122
|
|
|
123
|
+
/** @deprecated use fire(data, Emitter.Error.Ignore) */
|
|
58
124
|
public fireNoError(data: T) {
|
|
59
|
-
this.
|
|
60
|
-
if (!this._callbacks) return;
|
|
61
|
-
|
|
62
|
-
this.executing = true;
|
|
63
|
-
for (const callback of this._callbacks) {
|
|
64
|
-
try {
|
|
65
|
-
callback?.(data);
|
|
66
|
-
} catch (e) {
|
|
67
|
-
if (e instanceof Exit) {
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
console.error('Emitter.fireNoError: error ignored: %s', e instanceof Error ? e.stack : e);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
this.executing = false;
|
|
74
|
-
if (this._something_change_during_call) {
|
|
75
|
-
this.checkDeleted();
|
|
76
|
-
}
|
|
125
|
+
this.fire(data, FireErrorAction.Ignore);
|
|
77
126
|
}
|
|
78
127
|
|
|
79
128
|
get register(): EventRegister<T> {
|
|
@@ -91,20 +140,17 @@ export class Emitter<T = unknown> implements IEventEmitter<T> {
|
|
|
91
140
|
handle(callback: EventHandler<T>): IDisposable {
|
|
92
141
|
this.requireNotExecuting();
|
|
93
142
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const callbacks = this._callbacks;
|
|
97
|
-
callbacks.unshift(callback);
|
|
143
|
+
this._callbacks.unshift(callback);
|
|
98
144
|
|
|
99
145
|
return functionToDisposable(
|
|
100
146
|
nameObject(`removeListener(${objectName(callback)})`, () => {
|
|
101
|
-
const index =
|
|
147
|
+
const index = this._callbacks.indexOf(callback);
|
|
102
148
|
if (index === -1) return;
|
|
103
149
|
if (this.executing) {
|
|
104
150
|
this._something_change_during_call = true;
|
|
105
|
-
|
|
151
|
+
this._callbacks[index] = undefined;
|
|
106
152
|
} else {
|
|
107
|
-
|
|
153
|
+
this._callbacks.splice(index, 1);
|
|
108
154
|
}
|
|
109
155
|
}),
|
|
110
156
|
);
|
|
@@ -159,7 +205,8 @@ export class Emitter<T = unknown> implements IEventEmitter<T> {
|
|
|
159
205
|
if (this._disposed) return;
|
|
160
206
|
this._disposed = true;
|
|
161
207
|
|
|
162
|
-
this._callbacks =
|
|
208
|
+
this._callbacks.length = 0;
|
|
209
|
+
Object.assign(this, { _callbacks: null });
|
|
163
210
|
|
|
164
211
|
if (this._waittings) {
|
|
165
212
|
for (const rej of this._waittings) {
|
|
@@ -37,6 +37,10 @@ export class RequiredMap<K, V> extends Map<K, V> {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
if (Map.prototype.getOrInsert) {
|
|
41
|
+
RequiredMap.prototype.get = Map.prototype.getOrInsert as any;
|
|
42
|
+
}
|
|
43
|
+
|
|
40
44
|
/**
|
|
41
45
|
* A map that holds instances, automatically create new instance
|
|
42
46
|
*/
|
|
@@ -56,3 +60,9 @@ export abstract class InstanceMap<K, V> extends Map<K, V> {
|
|
|
56
60
|
return nv;
|
|
57
61
|
}
|
|
58
62
|
}
|
|
63
|
+
|
|
64
|
+
if (typeof Map.prototype.getOrInsertComputed === 'function') {
|
|
65
|
+
RequiredMap.prototype.get = function (this: InstanceMap<any, any>, id: any): any {
|
|
66
|
+
return this.getOrInsertComputed(id, (k) => this.instance(k));
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CanceledError, TimeoutError } from '@idlebox/errors';
|
|
2
2
|
import type { IDisposable } from '../lifecycle/dispose/disposable.js';
|
|
3
|
-
import type { TimeoutType } from '../schedule/local-type.js';
|
|
4
3
|
import { scheduler } from '../schedule/scheduler.js';
|
|
5
4
|
|
|
6
5
|
export type ValueCallback<T = any> = (value: T | Promise<T>) => void;
|
|
@@ -143,16 +142,16 @@ export class DeferredPromise<T, PT = any> {
|
|
|
143
142
|
};
|
|
144
143
|
}
|
|
145
144
|
|
|
146
|
-
|
|
145
|
+
private timer?: ITimeoutType;
|
|
147
146
|
#cancel_timeout() {
|
|
148
|
-
if (this
|
|
149
|
-
clearTimeout(this
|
|
150
|
-
this
|
|
147
|
+
if (this.timer) {
|
|
148
|
+
clearTimeout(this.timer);
|
|
149
|
+
this.timer = undefined;
|
|
151
150
|
}
|
|
152
151
|
}
|
|
153
152
|
timeout(ms: number) {
|
|
154
153
|
if (this.settled) throw new Error('no more timeout after settled');
|
|
155
|
-
this
|
|
154
|
+
this.timer = setTimeout(() => {
|
|
156
155
|
this.error(new TimeoutError(ms, 'promise not settled'));
|
|
157
156
|
}, ms);
|
|
158
157
|
|
package/src/re-export.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { DeferredPromise } from '../promise/deferred-promise.js';
|
|
2
|
-
import type { TimeoutType } from './local-type.js';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* 反复推迟的 setTimeout
|
|
6
5
|
*/
|
|
7
6
|
export class ExtendableTimer {
|
|
8
7
|
private readonly dfd = new DeferredPromise<void>();
|
|
9
|
-
|
|
8
|
+
public tmr?: ITimeoutType;
|
|
10
9
|
|
|
11
10
|
constructor(private readonly durationMs: number) {}
|
|
12
11
|
|
package/src/schedule/timeout.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TimeoutError } from '@idlebox/errors';
|
|
2
|
+
import { createStackTraceHolder } from '../error/stack-trace.js';
|
|
2
3
|
import { isNodeJs } from '../platform/os.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -6,10 +7,13 @@ import { isNodeJs } from '../platform/os.js';
|
|
|
6
7
|
* can not set to `true` on other platform (will throw "unref is not function" error).
|
|
7
8
|
* @returns promise reject with TimeoutError after specific time
|
|
8
9
|
*/
|
|
9
|
-
export function timeout(ms: number, error
|
|
10
|
+
export function timeout(ms: number, error?: string, boundary?: Function, unref?: boolean): Promise<never>;
|
|
11
|
+
export function timeout(ms: number, error: string = 'no response', boundary: Function = timeout, unref = false): Promise<never> {
|
|
12
|
+
const s = createStackTraceHolder('', boundary);
|
|
13
|
+
|
|
10
14
|
return new Promise((_, reject) => {
|
|
11
15
|
const timer = setTimeout(() => {
|
|
12
|
-
reject(new TimeoutError(ms, error));
|
|
16
|
+
reject(new TimeoutError(ms, error, s));
|
|
13
17
|
}, ms);
|
|
14
18
|
if (unref) (timer as any).unref();
|
|
15
19
|
});
|
|
@@ -42,8 +46,8 @@ export function raceTimeout<T>(ms: number, message: string, p: PromiseLike<T>):
|
|
|
42
46
|
*/
|
|
43
47
|
export function raceTimeout<T>(ms: number, message_or_p: string | PromiseLike<T>, p?: PromiseLike<T>): Promise<T> {
|
|
44
48
|
if (p) {
|
|
45
|
-
return Promise.race([p, timeout(ms, message_or_p as string, isNodeJs)]);
|
|
49
|
+
return Promise.race([p, timeout(ms, message_or_p as string, raceTimeout, isNodeJs)]);
|
|
46
50
|
} else {
|
|
47
|
-
return Promise.race([message_or_p as PromiseLike<T>, timeout(ms, undefined, isNodeJs)]);
|
|
51
|
+
return Promise.race([message_or_p as PromiseLike<T>, timeout(ms, undefined, raceTimeout, isNodeJs)]);
|
|
48
52
|
}
|
|
49
53
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local-type.d.ts","sourceRoot":"","sources":["../../src/schedule/local-type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AACxD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local-type.js","sourceRoot":"","sources":["../../src/schedule/local-type.ts"],"names":[],"mappings":""}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { FileBuilder, GenerateContext } from '@build-script/codegen';
|
|
2
|
-
|
|
3
|
-
export function concatStringType(a: string[]): string {
|
|
4
|
-
return a.join('');
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function generate(context: GenerateContext) {
|
|
8
|
-
let builder: FileBuilder;
|
|
9
|
-
if (context.file) {
|
|
10
|
-
builder = context.file('./concatType');
|
|
11
|
-
} else {
|
|
12
|
-
// TODO
|
|
13
|
-
builder = context as any;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const typeList = [];
|
|
17
|
-
const argList = [];
|
|
18
|
-
const returnList = [];
|
|
19
|
-
for (let i = 0; i < 20; i++) {
|
|
20
|
-
typeList.push(`T${i} extends string`);
|
|
21
|
-
argList.push(`t${i}: T${i}`);
|
|
22
|
-
returnList.push(`\${T${i}}`);
|
|
23
|
-
|
|
24
|
-
const type = typeList.join(', ');
|
|
25
|
-
const arg = argList.join(', ');
|
|
26
|
-
const ret = returnList.join('');
|
|
27
|
-
builder.append(`export function concatStringType\n\t<${type}>\n\t\t(${arg}):\n\t\`${ret}\`;`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
builder.copyFunctionDeclare('concatStringType');
|
|
31
|
-
}
|