@planet-matrix/mobius-model 0.6.0 → 0.10.1
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/CHANGELOG.md +50 -0
- package/oxlint.config.ts +1 -2
- package/package.json +29 -17
- package/scripts/build.ts +2 -52
- package/src/ai/README.md +1 -0
- package/src/ai/ai.ts +107 -0
- package/src/ai/chat-completion-ai/aihubmix-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/chat-completion-ai.ts +270 -0
- package/src/ai/chat-completion-ai/chat-completion.ts +189 -0
- package/src/ai/chat-completion-ai/index.ts +7 -0
- package/src/ai/chat-completion-ai/lingyiwanwu-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/ohmygpt-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/openai-next-chat-completion.ts +78 -0
- package/src/ai/embedding-ai/embedding-ai.ts +63 -0
- package/src/ai/embedding-ai/embedding.ts +50 -0
- package/src/ai/embedding-ai/index.ts +4 -0
- package/src/ai/embedding-ai/openai-next-embedding.ts +23 -0
- package/src/ai/index.ts +4 -0
- package/src/aio/README.md +100 -0
- package/src/aio/content.ts +141 -0
- package/src/aio/index.ts +3 -0
- package/src/aio/json.ts +127 -0
- package/src/aio/prompt.ts +246 -0
- package/src/basic/README.md +20 -15
- package/src/basic/error.ts +19 -5
- package/src/basic/function.ts +2 -2
- package/src/basic/index.ts +1 -0
- package/src/basic/promise.ts +141 -71
- package/src/basic/schedule.ts +111 -0
- package/src/basic/stream.ts +135 -25
- package/src/credential/README.md +107 -0
- package/src/credential/api-key.ts +158 -0
- package/src/credential/bearer.ts +73 -0
- package/src/credential/index.ts +4 -0
- package/src/credential/json-web-token.ts +96 -0
- package/src/credential/password.ts +170 -0
- package/src/cron/README.md +86 -0
- package/src/cron/cron.ts +87 -0
- package/src/cron/index.ts +1 -0
- package/src/drizzle/README.md +1 -0
- package/src/drizzle/drizzle.ts +1 -0
- package/src/drizzle/helper.ts +47 -0
- package/src/drizzle/index.ts +5 -0
- package/src/drizzle/infer.ts +52 -0
- package/src/drizzle/kysely.ts +8 -0
- package/src/drizzle/pagination.ts +198 -0
- package/src/email/README.md +1 -0
- package/src/email/index.ts +1 -0
- package/src/email/resend.ts +25 -0
- package/src/event/class-event-proxy.ts +5 -6
- package/src/event/common.ts +13 -3
- package/src/event/event-manager.ts +3 -3
- package/src/event/instance-event-proxy.ts +5 -6
- package/src/event/internal.ts +4 -4
- package/src/exception/README.md +28 -19
- package/src/exception/error/error.ts +123 -0
- package/src/exception/error/index.ts +2 -0
- package/src/exception/error/match.ts +38 -0
- package/src/exception/error/must-fix.ts +17 -0
- package/src/exception/index.ts +2 -0
- package/src/file-system/find.ts +53 -0
- package/src/file-system/index.ts +2 -0
- package/src/file-system/path.ts +76 -0
- package/src/file-system/resolve.ts +22 -0
- package/src/form/README.md +25 -0
- package/src/form/index.ts +1 -0
- package/src/form/inputor-controller/base.ts +861 -0
- package/src/form/inputor-controller/boolean.ts +39 -0
- package/src/form/inputor-controller/file.ts +39 -0
- package/src/form/inputor-controller/form.ts +179 -0
- package/src/form/inputor-controller/helper.ts +117 -0
- package/src/form/inputor-controller/index.ts +17 -0
- package/src/form/inputor-controller/multi-select.ts +99 -0
- package/src/form/inputor-controller/number.ts +116 -0
- package/src/form/inputor-controller/select.ts +109 -0
- package/src/form/inputor-controller/text.ts +82 -0
- package/src/http/READMD.md +1 -0
- package/src/http/api/api-core.ts +84 -0
- package/src/http/api/api-handler.ts +79 -0
- package/src/http/api/api-host.ts +47 -0
- package/src/http/api/api-result.ts +56 -0
- package/src/http/api/api-schema.ts +154 -0
- package/src/http/api/api-server.ts +130 -0
- package/src/http/api/api-test.ts +142 -0
- package/src/http/api/api-type.ts +34 -0
- package/src/http/api/api.ts +81 -0
- package/src/http/api/index.ts +11 -0
- package/src/http/api-adapter/api-core-node-http.ts +260 -0
- package/src/http/api-adapter/api-host-node-http.ts +156 -0
- package/src/http/api-adapter/api-result-arktype.ts +294 -0
- package/src/http/api-adapter/api-result-zod.ts +286 -0
- package/src/http/api-adapter/index.ts +5 -0
- package/src/http/bin/gen-api-list/gen-api-list.ts +126 -0
- package/src/http/bin/gen-api-list/index.ts +1 -0
- package/src/http/bin/gen-api-test/gen-api-test.ts +136 -0
- package/src/http/bin/gen-api-test/index.ts +1 -0
- package/src/http/bin/gen-api-type/calc-code.ts +25 -0
- package/src/http/bin/gen-api-type/gen-api-type.ts +127 -0
- package/src/http/bin/gen-api-type/index.ts +2 -0
- package/src/http/bin/index.ts +2 -0
- package/src/http/index.ts +3 -0
- package/src/huawei/README.md +1 -0
- package/src/huawei/index.ts +2 -0
- package/src/huawei/moderation/index.ts +1 -0
- package/src/huawei/moderation/moderation.ts +355 -0
- package/src/huawei/obs/esdk-obs-nodejs.d.ts +87 -0
- package/src/huawei/obs/index.ts +1 -0
- package/src/huawei/obs/obs.ts +42 -0
- package/src/index.ts +21 -2
- package/src/json/README.md +92 -0
- package/src/json/index.ts +1 -0
- package/src/json/repair.ts +18 -0
- package/src/log/logger.ts +15 -4
- package/src/openai/README.md +1 -0
- package/src/openai/index.ts +1 -0
- package/src/openai/openai.ts +509 -0
- package/src/orchestration/README.md +9 -7
- package/src/orchestration/dispatching/dispatcher.ts +83 -0
- package/src/orchestration/dispatching/index.ts +2 -0
- package/src/orchestration/dispatching/selector/base-selector.ts +39 -0
- package/src/orchestration/dispatching/selector/down-count-selector.ts +119 -0
- package/src/orchestration/dispatching/selector/index.ts +2 -0
- package/src/orchestration/index.ts +2 -0
- package/src/orchestration/scheduling/index.ts +2 -0
- package/src/orchestration/scheduling/scheduler.ts +103 -0
- package/src/orchestration/scheduling/task.ts +32 -0
- package/src/random/README.md +8 -7
- package/src/random/base.ts +66 -0
- package/src/random/index.ts +5 -1
- package/src/random/random-boolean.ts +40 -0
- package/src/random/random-integer.ts +60 -0
- package/src/random/random-number.ts +72 -0
- package/src/random/random-string.ts +66 -0
- package/src/request/README.md +108 -0
- package/src/request/fetch/base.ts +108 -0
- package/src/request/fetch/browser.ts +280 -0
- package/src/request/fetch/general.ts +20 -0
- package/src/request/fetch/index.ts +4 -0
- package/src/request/fetch/nodejs.ts +280 -0
- package/src/request/index.ts +2 -0
- package/src/request/request/base.ts +246 -0
- package/src/request/request/general.ts +63 -0
- package/src/request/request/index.ts +3 -0
- package/src/request/request/resource.ts +68 -0
- package/src/result/README.md +4 -0
- package/src/result/controller.ts +58 -0
- package/src/result/either.ts +363 -0
- package/src/result/generator.ts +168 -0
- package/src/result/index.ts +3 -0
- package/src/route/README.md +105 -0
- package/src/route/adapter/browser.ts +122 -0
- package/src/route/adapter/driver.ts +56 -0
- package/src/route/adapter/index.ts +2 -0
- package/src/route/index.ts +3 -0
- package/src/route/router/index.ts +2 -0
- package/src/route/router/route.ts +630 -0
- package/src/route/router/router.ts +1641 -0
- package/src/route/uri/hash.ts +307 -0
- package/src/route/uri/index.ts +7 -0
- package/src/route/uri/pathname.ts +376 -0
- package/src/route/uri/search.ts +412 -0
- package/src/service/README.md +1 -0
- package/src/service/index.ts +1 -0
- package/src/service/service.ts +110 -0
- package/src/socket/README.md +105 -0
- package/src/socket/client/index.ts +2 -0
- package/src/socket/client/socket-unit.ts +658 -0
- package/src/socket/client/socket.ts +203 -0
- package/src/socket/common/index.ts +2 -0
- package/src/socket/common/socket-unit-common.ts +23 -0
- package/src/socket/common/socket-unit-heartbeat.ts +427 -0
- package/src/socket/index.ts +3 -0
- package/src/socket/server/index.ts +3 -0
- package/src/socket/server/server.ts +183 -0
- package/src/socket/server/socket-unit.ts +448 -0
- package/src/socket/server/socket.ts +264 -0
- package/src/storage/table.ts +3 -3
- package/src/timer/expiration/expiration-manager.ts +3 -3
- package/src/timer/expiration/remaining-manager.ts +3 -3
- package/src/tube/README.md +99 -0
- package/src/tube/helper.ts +137 -0
- package/src/tube/index.ts +2 -0
- package/src/tube/tube.ts +880 -0
- package/src/weixin/README.md +1 -0
- package/src/weixin/index.ts +2 -0
- package/src/weixin/official-account/authorization.ts +157 -0
- package/src/weixin/official-account/index.ts +2 -0
- package/src/weixin/official-account/js-api.ts +132 -0
- package/src/weixin/open/index.ts +1 -0
- package/src/weixin/open/oauth2.ts +131 -0
- package/tests/unit/ai/ai.spec.ts +85 -0
- package/tests/unit/aio/content.spec.ts +105 -0
- package/tests/unit/aio/json.spec.ts +146 -0
- package/tests/unit/aio/prompt.spec.ts +111 -0
- package/tests/unit/basic/error.spec.ts +16 -4
- package/tests/unit/basic/promise.spec.ts +158 -50
- package/tests/unit/basic/schedule.spec.ts +74 -0
- package/tests/unit/basic/stream.spec.ts +90 -37
- package/tests/unit/credential/api-key.spec.ts +36 -0
- package/tests/unit/credential/bearer.spec.ts +23 -0
- package/tests/unit/credential/json-web-token.spec.ts +23 -0
- package/tests/unit/credential/password.spec.ts +40 -0
- package/tests/unit/cron/cron.spec.ts +84 -0
- package/tests/unit/event/class-event-proxy.spec.ts +3 -3
- package/tests/unit/event/event-manager.spec.ts +3 -3
- package/tests/unit/event/instance-event-proxy.spec.ts +3 -3
- package/tests/unit/exception/error/error.spec.ts +83 -0
- package/tests/unit/exception/error/match.spec.ts +81 -0
- package/tests/unit/form/inputor-controller/base.spec.ts +458 -0
- package/tests/unit/form/inputor-controller/boolean.spec.ts +30 -0
- package/tests/unit/form/inputor-controller/file.spec.ts +27 -0
- package/tests/unit/form/inputor-controller/form.spec.ts +120 -0
- package/tests/unit/form/inputor-controller/helper.spec.ts +67 -0
- package/tests/unit/form/inputor-controller/multi-select.spec.ts +34 -0
- package/tests/unit/form/inputor-controller/number.spec.ts +36 -0
- package/tests/unit/form/inputor-controller/select.spec.ts +49 -0
- package/tests/unit/form/inputor-controller/text.spec.ts +34 -0
- package/tests/unit/http/api/api-core-host.spec.ts +207 -0
- package/tests/unit/http/api/api-schema.spec.ts +120 -0
- package/tests/unit/http/api/api-server.spec.ts +363 -0
- package/tests/unit/http/api/api-test.spec.ts +117 -0
- package/tests/unit/http/api/api.spec.ts +121 -0
- package/tests/unit/http/api-adapter/node-http.spec.ts +187 -0
- package/tests/unit/identifier/uuid.spec.ts +0 -1
- package/tests/unit/json/repair.spec.ts +11 -0
- package/tests/unit/log/logger.spec.ts +19 -4
- package/tests/unit/openai/openai.spec.ts +64 -0
- package/tests/unit/orchestration/dispatching/dispatcher.spec.ts +41 -0
- package/tests/unit/orchestration/dispatching/selector/down-count-selector.spec.ts +81 -0
- package/tests/unit/orchestration/scheduling/scheduler.spec.ts +103 -0
- package/tests/unit/random/base.spec.ts +58 -0
- package/tests/unit/random/random-boolean.spec.ts +25 -0
- package/tests/unit/random/random-integer.spec.ts +32 -0
- package/tests/unit/random/random-number.spec.ts +33 -0
- package/tests/unit/random/random-string.spec.ts +22 -0
- package/tests/unit/request/fetch/browser.spec.ts +222 -0
- package/tests/unit/request/fetch/general.spec.ts +43 -0
- package/tests/unit/request/fetch/nodejs.spec.ts +225 -0
- package/tests/unit/request/request/base.spec.ts +382 -0
- package/tests/unit/request/request/general.spec.ts +160 -0
- package/tests/unit/result/controller.spec.ts +82 -0
- package/tests/unit/result/either.spec.ts +377 -0
- package/tests/unit/result/generator.spec.ts +273 -0
- package/tests/unit/route/router/route.spec.ts +430 -0
- package/tests/unit/route/router/router.spec.ts +407 -0
- package/tests/unit/route/uri/hash.spec.ts +72 -0
- package/tests/unit/route/uri/pathname.spec.ts +146 -0
- package/tests/unit/route/uri/search.spec.ts +107 -0
- package/tests/unit/socket/client.spec.ts +208 -0
- package/tests/unit/socket/server.spec.ts +133 -0
- package/tests/unit/socket/socket-unit-heartbeat.spec.ts +214 -0
- package/tests/unit/tube/helper.spec.ts +139 -0
- package/tests/unit/tube/tube.spec.ts +501 -0
- package/vite.config.ts +2 -1
- package/dist/index.js +0 -50
- package/dist/index.js.map +0 -209
- package/src/random/string.ts +0 -35
- package/tests/unit/random/string.spec.ts +0 -11
package/src/basic/README.md
CHANGED
|
@@ -2,48 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
## Description
|
|
4
4
|
|
|
5
|
-
Basic 模块提供面向 JavaScript 运行时值(runtime value
|
|
5
|
+
Basic 模块提供面向 JavaScript 运行时值(runtime value)的通用基础能力,用于承载一组稳定、可组合、低假设的便捷操作。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
这里所说的“运行时值”,既包括 primitive value,也包括 JavaScript 运行时原生提供的常见对象与接口,例如 `Function`、`Promise`、`ReadableStream`、`Date`、`Error`、`RegExp` 等。
|
|
8
|
+
|
|
9
|
+
它关注的不是某个具体业务领域,而是围绕运行时值展开、可以长期复用的基础处理能力。
|
|
8
10
|
|
|
9
11
|
## For Understanding
|
|
10
12
|
|
|
11
|
-
理解 Basic
|
|
13
|
+
理解 Basic 模块时,首先要把握它的核心边界:这里承载的是“运行时直接提供的值如何被方便、稳定地处理”,而不是“围绕某个自定义对象系统、业务模型或宿主入口建立长期语义”。只要某项能力的主要价值在于处理字符串、数字、布尔值、BigInt、符号(Symbol)、数组、对象、函数、Promise、Error、正则表达式(regular expression)、时间值、流(stream)等运行时值,它通常就有机会属于 Basic。
|
|
14
|
+
|
|
15
|
+
从这个角度看,`function`、`promise`、`stream` 与 `boolean`、`string`、`object`、`array`、`number` 没有本质区别,都是运行时已经给出的基础对象形态。
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
反过来说,如果某项能力的重点已经变成注册全局监听器、读取运行时上下文、感知平台能力、消费宿主级事件源,或围绕某类自定义对象建立独立问题域,那么它通常就不再属于 Basic。Basic 关心的是运行时值的通用处理语义,而不是环境级语义、业务对象语义或更高层的领域模型语义。
|
|
14
18
|
|
|
15
19
|
这也意味着 Basic 不是“随手工具箱”。一个能力只有在满足以下条件时,才适合进入这个模块:
|
|
16
20
|
|
|
17
|
-
-
|
|
21
|
+
- 它表达的是稳定、清楚、可复用的值级问题。
|
|
18
22
|
- 它对调用方前提的假设足够少,能在不同项目中长期成立。
|
|
19
|
-
-
|
|
23
|
+
- 它适合通过清楚的输入输出语义被组合,而不是依赖隐式上下文、特定业务约定或某个自定义对象体系的内部状态。
|
|
20
24
|
|
|
21
25
|
## For Using
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
当你需要把分散在业务代码中的基础判断、值转换、容器处理,以及围绕函数、Promise、流等运行时原生对象的便捷操作整理成稳定能力时,可以使用这个模块。它适合放在业务逻辑与语言原生能力之间,作为一层更可复用、更可测试的基础模型层。
|
|
24
28
|
|
|
25
29
|
当前公共能力大致可以按以下几类理解:
|
|
26
30
|
|
|
27
|
-
- 值判断与基础守卫:例如 primitive
|
|
31
|
+
- 值判断与基础守卫:例如 primitive、对象、数组、空值、数字特征等运行时判断,用于减少重复分支。
|
|
28
32
|
- 基础值处理:例如字符串、数字、布尔值、BigInt、符号等常见值类型的转换、裁剪、计算与格式化。
|
|
29
33
|
- 容器处理:例如数组与对象的筛选、映射、分区、裁剪、合并、字段选择与标准化,适合在进入业务模型前先整理数据形态。
|
|
30
|
-
-
|
|
34
|
+
- 函数相关:例如一次性调用、防抖、节流、组合、管道、记忆化、条件执行等围绕函数值展开的便捷能力。
|
|
31
35
|
- 异步与流处理:例如 Promise 队列、重试、轮询、失败结果表达,以及围绕 `ReadableStream` 的基础消费与转换。
|
|
32
36
|
- 时间、错误与正则辅助:例如时间格式化、异常字符串化、常见模式判断等值级辅助能力。
|
|
33
37
|
- 显式增强能力:如果某个能力会对内建对象做增强,它必须保持显式调用、行为可审查,并且不应成为其它公共能力成立的隐含前提。
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
如果你的问题已经需要环境感知、平台能力探测、全局异常监听,或需要围绕某类自定义对象建立独立问题域,应优先考虑 Environment、Exception 或其它更贴近问题域的模块,而不是继续把能力堆进 Basic。
|
|
36
40
|
|
|
37
41
|
## For Contributing
|
|
38
42
|
|
|
39
|
-
贡献 Basic
|
|
43
|
+
贡献 Basic 模块时,首要任务不是补齐一个方便函数,而是确认这项能力是否真的表达了稳定、可复用的运行时基础语义。这里应长期承载的是对运行时值的清楚整理,而不是对某个调用点的临时修补。
|
|
40
44
|
|
|
41
45
|
在扩展时,应优先遵守以下模块边界:
|
|
42
46
|
|
|
43
|
-
-
|
|
47
|
+
- 只收纳围绕运行时值展开的判断、转换、组合、格式化与其它稳定便捷操作。
|
|
44
48
|
- 不把环境探测、宿主监听、全局状态操纵或平台接入逻辑放入 Basic。
|
|
45
|
-
-
|
|
49
|
+
- 不为了省几行调用代码就公开一次性便捷包装;只有值得长期承诺的公共语义才应进入模块。
|
|
46
50
|
- 如果某项能力依赖显式增强内建对象,必须让增强保持可选,而不是让整个模块隐式建立在原型修改之上。
|
|
51
|
+
- 若新增能力主要是在围绕某类自定义对象、某套业务状态机、某个框架生命周期或某个宿主入口建立独立问题域,那么它通常应进入更贴近该问题域的模块,而不是留在 Basic。
|
|
47
52
|
|
|
48
53
|
### JSDoc 注释格式要求
|
|
49
54
|
|
|
@@ -74,14 +79,14 @@ Basic 模块提供面向 JavaScript 运行时值(runtime value)的通用基
|
|
|
74
79
|
- 子模块不需要有自己的 `README.md`。
|
|
75
80
|
- 子模块可以有自己的 `internal.ts` 文件,多个子模块共享的辅助元素应该放在父模块的 `internal.ts` 文件中,单个子模块共享的辅助元素应该放在该子模块的 `internal.ts` 文件中。
|
|
76
81
|
- 对模块依赖关系的要求(通常是不循环依赖或不反向依赖)与对 DRY 的要求可能产生冲突。此时,若复用的代码数量不大,可以适当牺牲 DRY,复制粘贴并保留必要的注释说明;若复用的代码数量较大,则可以将其抽象到新的文件或子模块中,如 `common.ts`,并在需要的地方导入使用。
|
|
77
|
-
- Basic
|
|
82
|
+
- Basic 的实现应优先保证输入输出语义直接、低副作用、可组合,而不是追求隐式魔法、业务耦合或依赖特定框架约定的包装。
|
|
78
83
|
|
|
79
84
|
### 导出策略要求
|
|
80
85
|
|
|
81
86
|
- 保持内部辅助项和内部符号为私有,不要让外部接入依赖临时性的内部结构。
|
|
82
87
|
- 每个模块都应有一个用于重导出所有公共 API 的 Barrel 文件。
|
|
83
88
|
- Barrel 文件应命名为 `index.ts`,放在模块目录根部,并且所有公共 API 都应从该文件导出。
|
|
84
|
-
-
|
|
89
|
+
- 新增公共能力时,应优先检查它是否表达稳定、清楚且值得长期维护的运行时基础语义,而不是某段实现细节、业务约定或一次性便捷暴露;仅在确认需要长期对外承诺时再加入 Barrel 导出。
|
|
85
90
|
|
|
86
91
|
### 测试要求
|
|
87
92
|
|
package/src/basic/error.ts
CHANGED
|
@@ -39,13 +39,27 @@ export const errorIsNetworkError = (error: unknown): error is Error => {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Stringifies an
|
|
42
|
+
* Stringifies an error into a readable format.
|
|
43
43
|
*/
|
|
44
|
-
export const
|
|
45
|
-
if (isError(
|
|
46
|
-
return `${
|
|
44
|
+
export const errorStringify = (error: unknown): string => {
|
|
45
|
+
if (isError(error)) {
|
|
46
|
+
return `${error.name}: ${error.message}`
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
|
-
return `${String(
|
|
49
|
+
return `${String(error)}`
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Converts a value to an Error object. If the value is already an Error,
|
|
55
|
+
* it is returned as is. Otherwise, a new Error is created with the
|
|
56
|
+
* stringified value as its message.
|
|
57
|
+
*/
|
|
58
|
+
export const toError = (value: unknown): Error => {
|
|
59
|
+
if (isError(value)) {
|
|
60
|
+
return value
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return new Error(String(value))
|
|
50
64
|
}
|
|
51
65
|
}
|
package/src/basic/function.ts
CHANGED
|
@@ -95,7 +95,7 @@ export const functionDebounceSimple = <T extends AnyFunction>(
|
|
|
95
95
|
fn: T,
|
|
96
96
|
ms: number
|
|
97
97
|
): FunctionDebouncedSimple<T> => {
|
|
98
|
-
let timer:
|
|
98
|
+
let timer: ReturnType<typeof setTimeout>
|
|
99
99
|
return (...args) => {
|
|
100
100
|
clearTimeout(timer)
|
|
101
101
|
timer = setTimeout(() => {
|
|
@@ -127,7 +127,7 @@ export const debounce = <T extends AnyFunction>(
|
|
|
127
127
|
fn: T,
|
|
128
128
|
ms: number
|
|
129
129
|
): FunctionDebounced<T> => {
|
|
130
|
-
let timer:
|
|
130
|
+
let timer: ReturnType<typeof setTimeout>
|
|
131
131
|
let waiting: AnyFunction[] = []
|
|
132
132
|
return async (...args) => {
|
|
133
133
|
clearTimeout(timer)
|
package/src/basic/index.ts
CHANGED
package/src/basic/promise.ts
CHANGED
|
@@ -6,16 +6,16 @@ import { isPlainObject } from "./is.ts"
|
|
|
6
6
|
* @example
|
|
7
7
|
* ```
|
|
8
8
|
* // Expect: 6
|
|
9
|
-
* const example1 = await promiseThen((value: number) => value * 2
|
|
9
|
+
* const example1 = await promiseThen(Promise.resolve(3), (value: number) => value * 2)
|
|
10
10
|
* // Expect: "ok!"
|
|
11
|
-
* const example2 = await promiseThen((value: string) => `${value}
|
|
11
|
+
* const example2 = await promiseThen(Promise.resolve("ok"), (value: string) => `${value}!`)
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
export const promiseThen = async <V, R>(
|
|
15
|
-
doSomething: (value: V) => R | PromiseLike<R>,
|
|
16
15
|
target: Promise<V>,
|
|
16
|
+
doSomething: (value: V) => R | PromiseLike<R>,
|
|
17
17
|
): Promise<R> => {
|
|
18
|
-
return await target.then(doSomething)
|
|
18
|
+
return await target.then((value) => doSomething(value))
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -24,16 +24,16 @@ export const promiseThen = async <V, R>(
|
|
|
24
24
|
* @example
|
|
25
25
|
* ```
|
|
26
26
|
* // Expect: "fallback"
|
|
27
|
-
* const example1 = await promiseCatch(
|
|
27
|
+
* const example1 = await promiseCatch(Promise.reject(new Error("x")), () => "fallback")
|
|
28
28
|
* // Expect: 3
|
|
29
|
-
* const example2 = await promiseCatch(() => 0
|
|
29
|
+
* const example2 = await promiseCatch(Promise.resolve(3), () => 0)
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
32
|
export const promiseCatch = async <V, R>(
|
|
33
|
-
doSomething: (reason: unknown) => R | PromiseLike<R>,
|
|
34
33
|
target: Promise<V>,
|
|
34
|
+
doSomething: (reason: unknown) => R | PromiseLike<R>,
|
|
35
35
|
): Promise<V | R> => {
|
|
36
|
-
return await target.catch(doSomething)
|
|
36
|
+
return await target.catch((reason: unknown) => doSomething(reason))
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -43,25 +43,54 @@ export const promiseCatch = async <V, R>(
|
|
|
43
43
|
* ```
|
|
44
44
|
* let cleaned = false
|
|
45
45
|
* // Expect: 10
|
|
46
|
-
* const example1 = await promiseFinally(() => { cleaned = true }
|
|
46
|
+
* const example1 = await promiseFinally(Promise.resolve(10), () => { cleaned = true })
|
|
47
47
|
* // Expect: true
|
|
48
48
|
* const example2 = cleaned
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
51
|
export const promiseFinally = async <V>(
|
|
52
|
-
doSomething: () => void,
|
|
53
52
|
target: Promise<V>,
|
|
53
|
+
doSomething: () => void,
|
|
54
54
|
): Promise<V> => {
|
|
55
|
-
return await target.finally(doSomething)
|
|
55
|
+
return await target.finally(() => doSomething())
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface PromiseDeferred<V> {
|
|
59
|
+
promise: Promise<V>
|
|
60
|
+
resolve: (value: V) => void
|
|
61
|
+
reject: (reason: unknown) => void
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create a deferred promise with external resolve and reject functions.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```
|
|
68
|
+
* const deferred = promiseDeferred<number>()
|
|
69
|
+
* // Expect: typeof deferred.resolve === "function"
|
|
70
|
+
* const example1 = typeof deferred.resolve
|
|
71
|
+
* deferred.resolve(42)
|
|
72
|
+
* const example2 = await deferred.promise
|
|
73
|
+
* // Expect: 42
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export const promiseDeferred = <V>(): PromiseDeferred<V> => {
|
|
77
|
+
let externalResolve!: (value: V) => void
|
|
78
|
+
let externalReject!: (reason: unknown) => void
|
|
79
|
+
const promise = new Promise<V>((resolve, reject) => {
|
|
80
|
+
externalResolve = resolve
|
|
81
|
+
externalReject = reject
|
|
82
|
+
})
|
|
83
|
+
return { promise, resolve: externalResolve, reject: externalReject }
|
|
56
84
|
}
|
|
57
85
|
|
|
58
|
-
const INTERNAL_PROMISE_FAIL_RESULT_TYPE: symbol = Symbol("fail")
|
|
86
|
+
const INTERNAL_PROMISE_FAIL_RESULT_TYPE: unique symbol = Symbol("fail")
|
|
87
|
+
type InternalPromiseFailResultType = typeof INTERNAL_PROMISE_FAIL_RESULT_TYPE
|
|
59
88
|
|
|
60
89
|
/**
|
|
61
90
|
* 表示标准化的 Promise 失败结果。
|
|
62
91
|
*/
|
|
63
92
|
export interface PromiseFailResult {
|
|
64
|
-
__type__:
|
|
93
|
+
__type__: InternalPromiseFailResultType
|
|
65
94
|
reason: unknown
|
|
66
95
|
}
|
|
67
96
|
|
|
@@ -75,14 +104,23 @@ export interface PromiseIndexedFailResult extends PromiseFailResult {
|
|
|
75
104
|
/**
|
|
76
105
|
* 根据拒因构造标准化的 Promise 失败结果。
|
|
77
106
|
*/
|
|
78
|
-
export const
|
|
107
|
+
export const promiseCreateFailResult = (reason: unknown): PromiseFailResult => {
|
|
79
108
|
return { __type__: INTERNAL_PROMISE_FAIL_RESULT_TYPE, reason }
|
|
80
109
|
}
|
|
81
110
|
/**
|
|
82
111
|
* 判断目标值是否为标准化的 Promise 失败结果。
|
|
83
112
|
*/
|
|
84
|
-
export const
|
|
85
|
-
|
|
113
|
+
export const promiseIsFailResult = (target: unknown): target is PromiseFailResult => {
|
|
114
|
+
if (isPlainObject(target) === false) {
|
|
115
|
+
return false
|
|
116
|
+
}
|
|
117
|
+
if ("__type__" in target === false) {
|
|
118
|
+
return false
|
|
119
|
+
}
|
|
120
|
+
if (target["__type__"] !== INTERNAL_PROMISE_FAIL_RESULT_TYPE) {
|
|
121
|
+
return false
|
|
122
|
+
}
|
|
123
|
+
return true
|
|
86
124
|
}
|
|
87
125
|
/**
|
|
88
126
|
* 用作 `Promise.catch` 的 `onrejected` 回调,并返回标准化失败结果。
|
|
@@ -98,9 +136,8 @@ export const promiseFilterSuccessResults = <V>(
|
|
|
98
136
|
results: Array<V | PromiseFailResult>,
|
|
99
137
|
): V[] => {
|
|
100
138
|
const filtered = results.filter(result => {
|
|
101
|
-
return
|
|
139
|
+
return promiseIsFailResult(result) === false
|
|
102
140
|
})
|
|
103
|
-
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
104
141
|
return filtered as V[]
|
|
105
142
|
}
|
|
106
143
|
/**
|
|
@@ -112,7 +149,7 @@ export const promiseFilterFailResults = <V>(
|
|
|
112
149
|
const filtered = results.reduce<PromiseIndexedFailResult[]>((
|
|
113
150
|
accumulatedResults, currentResult, index
|
|
114
151
|
) => {
|
|
115
|
-
if (
|
|
152
|
+
if (promiseIsFailResult(currentResult)) {
|
|
116
153
|
accumulatedResults.push({ ...currentResult, index })
|
|
117
154
|
}
|
|
118
155
|
return accumulatedResults
|
|
@@ -131,8 +168,10 @@ interface PromiseQueueRestPromiseMakerContext<V, S = unknown> {
|
|
|
131
168
|
previousResult: V | PromiseFailResult
|
|
132
169
|
state: S
|
|
133
170
|
}
|
|
134
|
-
type PromiseQueueFirstPromiseMaker<T, S = unknown>
|
|
135
|
-
|
|
171
|
+
type PromiseQueueFirstPromiseMaker<T, S = unknown>
|
|
172
|
+
= (context: PromiseQueueFirstPromiseMakerContext<S>) => Promise<T>
|
|
173
|
+
type PromiseQueueRestPromiseMaker<T, S = unknown>
|
|
174
|
+
= (context: PromiseQueueRestPromiseMakerContext<T, S>) => Promise<T>
|
|
136
175
|
type PromiseQueuePromiseMakers<T, S = unknown> = [
|
|
137
176
|
PromiseQueueFirstPromiseMaker<T, S>,
|
|
138
177
|
...Array<PromiseQueueRestPromiseMaker<T, S>>
|
|
@@ -155,7 +194,7 @@ export interface PromiseQueueOptions {
|
|
|
155
194
|
* // Expect: [1, 2]
|
|
156
195
|
* const example1 = await promiseQueue<number>([
|
|
157
196
|
* async () => 1,
|
|
158
|
-
* async ({ previousResult }) => (
|
|
197
|
+
* async ({ previousResult }) => (promiseIsFailResult(previousResult) ? 0 : previousResult + 1),
|
|
159
198
|
* ])
|
|
160
199
|
* ```
|
|
161
200
|
*/
|
|
@@ -169,7 +208,6 @@ export const promiseQueue = async <T, S = unknown>(
|
|
|
169
208
|
let context: PromiseQueueFirstPromiseMakerContext<S> | PromiseQueueRestPromiseMakerContext<T, S> = {
|
|
170
209
|
index: 0,
|
|
171
210
|
hasPreviousResult: false,
|
|
172
|
-
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
173
211
|
state: undefined as unknown as S
|
|
174
212
|
}
|
|
175
213
|
|
|
@@ -205,18 +243,20 @@ export const promiseQueue = async <T, S = unknown>(
|
|
|
205
243
|
}
|
|
206
244
|
|
|
207
245
|
interface PromiseRetryFirstPromiseMakerContext<S = unknown> {
|
|
208
|
-
|
|
246
|
+
index: number
|
|
209
247
|
hasPreviousResult: false
|
|
210
248
|
state: S
|
|
211
249
|
}
|
|
212
250
|
interface PromiseRetryRestPromiseMakerContext<T, S = unknown> {
|
|
213
|
-
|
|
251
|
+
index: number
|
|
214
252
|
hasPreviousResult: true
|
|
215
253
|
previousResult: T | PromiseFailResult
|
|
216
254
|
state: S
|
|
217
255
|
}
|
|
218
256
|
type PromiseRetryPromiseMaker<T, S = unknown> = (
|
|
219
|
-
context:
|
|
257
|
+
context:
|
|
258
|
+
| PromiseRetryFirstPromiseMakerContext<S>
|
|
259
|
+
| PromiseRetryRestPromiseMakerContext<T, S>
|
|
220
260
|
) => Promise<T>
|
|
221
261
|
|
|
222
262
|
/**
|
|
@@ -228,9 +268,10 @@ export interface PromiseRetryOptions {
|
|
|
228
268
|
*/
|
|
229
269
|
breakTime?: number
|
|
230
270
|
/**
|
|
271
|
+
* `0` 表示仅执行首次尝试,不进行额外重试。
|
|
231
272
|
* @default Infinity
|
|
232
273
|
*/
|
|
233
|
-
|
|
274
|
+
maxTryIndex?: number | undefined
|
|
234
275
|
}
|
|
235
276
|
/**
|
|
236
277
|
* Retry while the predicate indicates the result is not acceptable.
|
|
@@ -257,34 +298,33 @@ export const promiseRetryWhile = async <T, S = unknown>(
|
|
|
257
298
|
): Promise<T | PromiseFailResult> => {
|
|
258
299
|
const {
|
|
259
300
|
breakTime = 0,
|
|
260
|
-
|
|
301
|
+
maxTryIndex = Infinity,
|
|
261
302
|
} = options ?? {}
|
|
262
303
|
|
|
263
|
-
if (
|
|
264
|
-
throw new Error("`
|
|
304
|
+
if (maxTryIndex < 0) {
|
|
305
|
+
throw new Error("`maxTryIndex` must be greater than or equal to 0.")
|
|
265
306
|
}
|
|
266
307
|
|
|
267
|
-
let
|
|
308
|
+
let index = 0
|
|
268
309
|
// oxlint-disable-next-line no-accumulating-spread
|
|
269
310
|
let context: PromiseRetryFirstPromiseMakerContext<S> | PromiseRetryRestPromiseMakerContext<T, S> = {
|
|
270
|
-
|
|
311
|
+
index,
|
|
271
312
|
hasPreviousResult: false,
|
|
272
|
-
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
273
313
|
state: undefined as unknown as S
|
|
274
314
|
}
|
|
275
315
|
let result = await promiseMaker(context).catch(promiseCatchToFailResult)
|
|
276
316
|
|
|
277
317
|
while (
|
|
278
|
-
(
|
|
279
|
-
&&
|
|
318
|
+
(promiseIsFailResult(result) || (await predicate(result)))
|
|
319
|
+
&& index < maxTryIndex
|
|
280
320
|
) {
|
|
281
|
-
|
|
321
|
+
index = index + 1
|
|
282
322
|
// oxlint-disable-next-line no-loop-func
|
|
283
323
|
result = await new Promise<T | PromiseFailResult>((resolve) => {
|
|
284
324
|
setTimeout(() => {
|
|
285
325
|
context = {
|
|
286
326
|
...context,
|
|
287
|
-
|
|
327
|
+
index,
|
|
288
328
|
hasPreviousResult: true,
|
|
289
329
|
previousResult: result,
|
|
290
330
|
}
|
|
@@ -315,40 +355,39 @@ export const promiseRetryWhile = async <T, S = unknown>(
|
|
|
315
355
|
* @see {@link promiseRetryWhile}
|
|
316
356
|
*/
|
|
317
357
|
export const promiseRetryUntil = async <T, S = unknown>(
|
|
318
|
-
predicate: (value: T,
|
|
358
|
+
predicate: (value: T, index: number) => boolean | Promise<boolean>,
|
|
319
359
|
promiseMaker: PromiseRetryPromiseMaker<T, S>,
|
|
320
360
|
options?: PromiseRetryOptions | undefined,
|
|
321
361
|
): Promise<T | PromiseFailResult> => {
|
|
322
362
|
const {
|
|
323
363
|
breakTime = 0,
|
|
324
|
-
|
|
364
|
+
maxTryIndex = Infinity,
|
|
325
365
|
} = options ?? {}
|
|
326
366
|
|
|
327
|
-
if (
|
|
328
|
-
throw new Error("`
|
|
367
|
+
if (maxTryIndex < 0) {
|
|
368
|
+
throw new Error("`maxTryIndex` must be greater than or equal to 0.")
|
|
329
369
|
}
|
|
330
370
|
|
|
331
|
-
let
|
|
371
|
+
let index = 0
|
|
332
372
|
// oxlint-disable-next-line no-accumulating-spread
|
|
333
373
|
let context: PromiseRetryFirstPromiseMakerContext<S> | PromiseRetryRestPromiseMakerContext<T, S> = {
|
|
334
|
-
|
|
374
|
+
index,
|
|
335
375
|
hasPreviousResult: false,
|
|
336
|
-
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
337
376
|
state: undefined as unknown as S
|
|
338
377
|
}
|
|
339
378
|
let result = await promiseMaker(context).catch(promiseCatchToFailResult)
|
|
340
379
|
|
|
341
380
|
while (
|
|
342
|
-
(
|
|
343
|
-
&&
|
|
381
|
+
(promiseIsFailResult(result) || !(await predicate(result, index)))
|
|
382
|
+
&& index < maxTryIndex
|
|
344
383
|
) {
|
|
345
|
-
|
|
384
|
+
index = index + 1
|
|
346
385
|
// oxlint-disable-next-line no-loop-func
|
|
347
386
|
result = await new Promise<T | PromiseFailResult>((resolve) => {
|
|
348
387
|
setTimeout(() => {
|
|
349
388
|
context = {
|
|
350
389
|
...context,
|
|
351
|
-
|
|
390
|
+
index,
|
|
352
391
|
hasPreviousResult: true,
|
|
353
392
|
previousResult: result
|
|
354
393
|
}
|
|
@@ -362,13 +401,14 @@ export const promiseRetryUntil = async <T, S = unknown>(
|
|
|
362
401
|
|
|
363
402
|
/**
|
|
364
403
|
* Start periodic asynchronous execution and return a function to stop it.
|
|
404
|
+
* Rejected runs are logged and ignored to avoid unhandled promise rejections.
|
|
365
405
|
*
|
|
366
406
|
* @example
|
|
367
407
|
* ```
|
|
368
408
|
* const records: number[] = []
|
|
369
|
-
* const stop = promiseInterval(10, async (
|
|
370
|
-
* records.push(
|
|
371
|
-
* return
|
|
409
|
+
* const stop = promiseInterval(10, async (index) => {
|
|
410
|
+
* records.push(index)
|
|
411
|
+
* return index
|
|
372
412
|
* })
|
|
373
413
|
* // Later: stop()
|
|
374
414
|
* // Expect: typeof stop === "function"
|
|
@@ -377,13 +417,15 @@ export const promiseRetryUntil = async <T, S = unknown>(
|
|
|
377
417
|
*/
|
|
378
418
|
export const promiseInterval = <T>(
|
|
379
419
|
interval: number,
|
|
380
|
-
promiseMaker: (
|
|
420
|
+
promiseMaker: (index: number) => Promise<T>,
|
|
381
421
|
): (() => void) => {
|
|
382
|
-
let
|
|
422
|
+
let index = 0
|
|
383
423
|
|
|
384
424
|
const intervalID = setInterval(() => {
|
|
385
|
-
void promiseMaker(
|
|
386
|
-
|
|
425
|
+
void promiseMaker(index).catch((error: unknown) => {
|
|
426
|
+
console.error("[promiseInterval] unexpected error occurred:", error)
|
|
427
|
+
})
|
|
428
|
+
index = index + 1
|
|
387
429
|
}, interval)
|
|
388
430
|
|
|
389
431
|
return () => {
|
|
@@ -392,18 +434,20 @@ export const promiseInterval = <T>(
|
|
|
392
434
|
}
|
|
393
435
|
|
|
394
436
|
interface PromiseForeverFirstPromiseMakerContext<S = unknown> {
|
|
395
|
-
|
|
437
|
+
index: number
|
|
396
438
|
hasPreviousResult: false
|
|
397
439
|
state: S
|
|
398
440
|
}
|
|
399
441
|
interface PromiseForeverRestPromiseMakerContext<T, S = unknown> {
|
|
400
|
-
|
|
442
|
+
index: number
|
|
401
443
|
hasPreviousResult: true
|
|
402
444
|
previousResult: T | PromiseFailResult
|
|
403
445
|
state: S
|
|
404
446
|
}
|
|
405
447
|
type PromiseForeverPromiseMaker<T, S = unknown> = (
|
|
406
|
-
context:
|
|
448
|
+
context:
|
|
449
|
+
| PromiseForeverFirstPromiseMakerContext<S>
|
|
450
|
+
| PromiseForeverRestPromiseMakerContext<T, S>
|
|
407
451
|
) => Promise<T>
|
|
408
452
|
|
|
409
453
|
/**
|
|
@@ -414,60 +458,80 @@ export interface PromiseForeverOptions {
|
|
|
414
458
|
* @default 0
|
|
415
459
|
*/
|
|
416
460
|
breakTime?: number | undefined
|
|
417
|
-
onRejected?: ((
|
|
461
|
+
onRejected?: ((index: number, result: PromiseFailResult) => void) | undefined
|
|
462
|
+
}
|
|
463
|
+
export interface PromiseForeverResult {
|
|
464
|
+
index: number
|
|
465
|
+
isStopped: boolean
|
|
466
|
+
stop: () => void
|
|
418
467
|
}
|
|
419
468
|
/**
|
|
420
469
|
* Continuously execute an async maker forever with optional delay and rejection hook.
|
|
421
470
|
*
|
|
471
|
+
* - 至少会执行一次,`stop()` 可以用来提前停止后续执行。
|
|
472
|
+
* - `index` 从 `0` 开始,表示当前执行轮次。
|
|
473
|
+
* - 如果某一轮结束后已经排入了下一轮的定时器,调用 `stop()` 不会取消那一轮;
|
|
474
|
+
* 它只会阻止后续继续排入新的轮次。
|
|
475
|
+
*
|
|
422
476
|
* @example
|
|
423
477
|
* ```
|
|
424
478
|
* let times = 0
|
|
425
|
-
* promiseForever(async () => {
|
|
479
|
+
* const controller = promiseForever(async () => {
|
|
426
480
|
* times = times + 1
|
|
427
481
|
* return times
|
|
428
482
|
* }, { breakTime: 0 })
|
|
429
|
-
*
|
|
430
|
-
*
|
|
483
|
+
* controller.stop()
|
|
484
|
+
* // Expect: typeof controller.stop === "function"
|
|
485
|
+
* const example1 = typeof controller.stop
|
|
431
486
|
* ```
|
|
432
487
|
*/
|
|
433
488
|
export const promiseForever = <T, S = unknown>(
|
|
434
489
|
promiseMaker: PromiseForeverPromiseMaker<T, S>,
|
|
435
490
|
options?: PromiseForeverOptions | undefined,
|
|
436
|
-
):
|
|
491
|
+
): PromiseForeverResult => {
|
|
437
492
|
const {
|
|
438
493
|
breakTime = 0,
|
|
439
494
|
onRejected,
|
|
440
495
|
} = options ?? {}
|
|
441
496
|
|
|
442
|
-
let
|
|
497
|
+
let index = 0
|
|
443
498
|
let context: PromiseForeverFirstPromiseMakerContext<S> | PromiseForeverRestPromiseMakerContext<T, S> = {
|
|
444
|
-
|
|
499
|
+
index,
|
|
445
500
|
hasPreviousResult: false,
|
|
446
|
-
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
447
501
|
state: undefined as unknown as S
|
|
448
502
|
}
|
|
503
|
+
const foreverResult: PromiseForeverResult = {
|
|
504
|
+
index,
|
|
505
|
+
isStopped: false,
|
|
506
|
+
stop: () => {
|
|
507
|
+
foreverResult.isStopped = true
|
|
508
|
+
}
|
|
509
|
+
}
|
|
449
510
|
|
|
450
511
|
const handlePromise = (result: T | PromiseFailResult): void => {
|
|
451
|
-
time = time + 1
|
|
452
512
|
setTimeout(() => {
|
|
513
|
+
index = index + 1
|
|
453
514
|
context = {
|
|
454
515
|
...context,
|
|
455
|
-
|
|
516
|
+
index,
|
|
456
517
|
hasPreviousResult: true,
|
|
457
518
|
previousResult: result
|
|
458
519
|
}
|
|
520
|
+
foreverResult.index = index
|
|
459
521
|
runPromise(context)
|
|
460
522
|
}, breakTime)
|
|
461
523
|
}
|
|
462
524
|
const runPromise = (
|
|
463
|
-
context:
|
|
525
|
+
context:
|
|
526
|
+
| PromiseForeverFirstPromiseMakerContext<S>
|
|
527
|
+
| PromiseForeverRestPromiseMakerContext<T, S>
|
|
464
528
|
): void => {
|
|
465
529
|
void promiseMaker(context)
|
|
466
530
|
.catch((error: unknown) => {
|
|
467
531
|
const failedResult = promiseCatchToFailResult(error)
|
|
468
532
|
if (onRejected !== undefined) {
|
|
469
533
|
try {
|
|
470
|
-
onRejected(
|
|
534
|
+
onRejected(index, failedResult)
|
|
471
535
|
}
|
|
472
536
|
catch {
|
|
473
537
|
// omit exceptions from execution of `onRejected`
|
|
@@ -478,8 +542,14 @@ export const promiseForever = <T, S = unknown>(
|
|
|
478
542
|
}
|
|
479
543
|
return failedResult
|
|
480
544
|
})
|
|
481
|
-
.then(result =>
|
|
545
|
+
.then(result => {
|
|
546
|
+
if (foreverResult.isStopped === false) {
|
|
547
|
+
handlePromise(result)
|
|
548
|
+
}
|
|
549
|
+
})
|
|
482
550
|
}
|
|
483
551
|
|
|
484
552
|
runPromise(context)
|
|
553
|
+
|
|
554
|
+
return foreverResult
|
|
485
555
|
}
|