@lppx/nlearn 1.1.8 → 1.1.10
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/dist/src/cli/cli.js +11 -6
- package/dist/src/demo/class/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +6 -0
- package/dist/src/demo/class/02-/347/273/247/346/211/277/344/270/216/345/244/232/346/200/201.js +6 -0
- package/dist/src/demo/class/03-/351/235/231/346/200/201/346/210/220/345/221/230/344/270/216/345/215/225/344/276/213.js +6 -0
- package/dist/src/demo/class/04-/346/216/245/345/217/243/344/270/216/345/256/236/347/216/260.js +7 -0
- package/dist/src/demo/commander/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +6 -0
- package/dist/src/demo/commander/02-/345/221/275/344/273/244/347/263/273/347/273/237.js +6 -0
- package/dist/src/demo/commander/03-/351/253/230/347/272/247/347/211/271/346/200/247.js +6 -0
- package/dist/src/demo/commander/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +4 -0
- package/dist/src/demo/esm/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +6 -0
- package/dist/src/demo/esm/02-/345/257/274/345/207/272/350/257/255/346/263/225.js +8 -0
- package/dist/src/demo/esm/03-/345/257/274/345/205/245/350/257/255/346/263/225.js +9 -2
- package/dist/src/demo/esm/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +8 -0
- package/dist/src/demo/fuse/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +5 -0
- package/dist/src/demo/fuse/02-/351/253/230/347/272/247/346/220/234/347/264/242.js +6 -0
- package/dist/src/demo/fuse/03-/351/205/215/347/275/256/350/257/246/350/247/243.js +6 -0
- package/dist/src/demo/fuse/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +5 -0
- package/dist/src/demo/inquirer/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +6 -0
- package/dist/src/demo/inquirer/02-/351/200/211/346/213/251/347/261/273/345/236/213.js +6 -0
- package/dist/src/demo/inquirer/03-/351/253/230/347/272/247/347/211/271/346/200/247.js +6 -0
- package/dist/src/demo/inquirer/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +5 -0
- package/dist/src/demo/promise-async/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +267 -0
- package/dist/src/demo/promise-async/02-/345/271/266/345/217/221/346/216/247/345/210/266.js +304 -0
- package/dist/src/demo/promise-async/03-/351/253/230/347/272/247/346/250/241/345/274/217.js +311 -0
- package/dist/src/demo/promise-async/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +349 -0
- package/dist/src/demo/prompts/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +5 -0
- package/dist/src/demo/prompts/02-/346/217/220/347/244/272/347/261/273/345/236/213.js +7 -0
- package/dist/src/demo/prompts/03-/351/253/230/347/272/247/347/211/271/346/200/247.js +6 -0
- package/dist/src/demo/prompts/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +4 -0
- package/dist/src/demo/prompts/05-/346/250/241/347/263/212/350/241/245/345/205/250.js +6 -0
- package/dist/src/demo/yargs/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +5 -0
- package/dist/src/demo/yargs/02-/345/221/275/344/273/244/347/263/273/347/273/237.js +6 -0
- package/dist/src/demo/yargs/03-/351/253/230/347/272/247/347/211/271/346/200/247.js +6 -0
- package/dist/src/demo/yargs/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Promise 并发控制
|
|
4
|
+
* ================
|
|
5
|
+
* 本文件介绍 Promise 的并发处理方法:Promise.all、Promise.race、Promise.allSettled、Promise.any
|
|
6
|
+
* 适用于 Node.js >= 14.0.0
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.promiseAllDemo = promiseAllDemo;
|
|
10
|
+
exports.promiseAllWithFailure = promiseAllWithFailure;
|
|
11
|
+
exports.promiseAllSettledDemo = promiseAllSettledDemo;
|
|
12
|
+
exports.promiseRaceDemo = promiseRaceDemo;
|
|
13
|
+
exports.timeoutControl = timeoutControl;
|
|
14
|
+
exports.promiseAnyDemo = promiseAnyDemo;
|
|
15
|
+
exports.comparePromiseMethods = comparePromiseMethods;
|
|
16
|
+
// #region 示例1: Promise.all - 等待所有 Promise 完成
|
|
17
|
+
/**
|
|
18
|
+
* Promise.all 会等待所有 Promise 都成功,如果有一个失败则立即失败
|
|
19
|
+
*/
|
|
20
|
+
async function promiseAllDemo() {
|
|
21
|
+
console.log('=== Promise.all 示例 ===\n');
|
|
22
|
+
// 模拟多个异步任务
|
|
23
|
+
function fetchUser(id) {
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
const delay = Math.random() * 1000 + 500;
|
|
26
|
+
setTimeout(() => {
|
|
27
|
+
console.log(`用户 ${id} 数据获取完成 (耗时 ${delay.toFixed(0)}ms)`);
|
|
28
|
+
resolve({ id, name: `用户${id}` });
|
|
29
|
+
}, delay);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
console.log('开始并发获取多个用户数据...\n');
|
|
34
|
+
const startTime = Date.now();
|
|
35
|
+
// 并发执行多个 Promise
|
|
36
|
+
const users = await Promise.all([
|
|
37
|
+
fetchUser(1),
|
|
38
|
+
fetchUser(2),
|
|
39
|
+
fetchUser(3),
|
|
40
|
+
fetchUser(4),
|
|
41
|
+
]);
|
|
42
|
+
const endTime = Date.now();
|
|
43
|
+
console.log('\n所有用户数据:', users);
|
|
44
|
+
console.log(`总耗时: ${endTime - startTime}ms`);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error('获取失败:', error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// #endregion
|
|
51
|
+
// #region 示例2: Promise.all 的失败处理
|
|
52
|
+
/**
|
|
53
|
+
* 演示 Promise.all 在遇到失败时的行为
|
|
54
|
+
*/
|
|
55
|
+
async function promiseAllWithFailure() {
|
|
56
|
+
console.log('\n=== Promise.all 失败处理 ===\n');
|
|
57
|
+
function fetchData(id, shouldFail) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
if (shouldFail) {
|
|
61
|
+
console.log(`任务 ${id} 失败`);
|
|
62
|
+
reject(new Error(`任务 ${id} 失败`));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(`任务 ${id} 成功`);
|
|
66
|
+
resolve(`任务 ${id} 的结果`);
|
|
67
|
+
}
|
|
68
|
+
}, 1000);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
console.log('开始执行任务(其中一个会失败)...\n');
|
|
73
|
+
const results = await Promise.all([
|
|
74
|
+
fetchData(1, false),
|
|
75
|
+
fetchData(2, true), // 这个会失败
|
|
76
|
+
fetchData(3, false),
|
|
77
|
+
]);
|
|
78
|
+
console.log('所有结果:', results);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error instanceof Error) {
|
|
82
|
+
console.error('\nPromise.all 被中断:', error.message);
|
|
83
|
+
console.log('注意:即使只有一个失败,Promise.all 也会立即失败');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// #endregion
|
|
88
|
+
// #region 示例3: Promise.allSettled - 等待所有 Promise 完成(无论成功或失败)
|
|
89
|
+
/**
|
|
90
|
+
* Promise.allSettled 会等待所有 Promise 完成,无论成功还是失败
|
|
91
|
+
* Node.js >= 12.9.0
|
|
92
|
+
*/
|
|
93
|
+
async function promiseAllSettledDemo() {
|
|
94
|
+
console.log('\n=== Promise.allSettled 示例 ===\n');
|
|
95
|
+
function fetchData(id, shouldFail) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
if (shouldFail) {
|
|
99
|
+
reject(new Error(`任务 ${id} 失败`));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
resolve(`任务 ${id} 的结果`);
|
|
103
|
+
}
|
|
104
|
+
}, 1000);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
console.log('开始执行任务(部分会失败)...\n');
|
|
108
|
+
const results = await Promise.allSettled([
|
|
109
|
+
fetchData(1, false),
|
|
110
|
+
fetchData(2, true),
|
|
111
|
+
fetchData(3, false),
|
|
112
|
+
fetchData(4, true),
|
|
113
|
+
]);
|
|
114
|
+
console.log('\n所有任务完成,结果如下:\n');
|
|
115
|
+
results.forEach((result, index) => {
|
|
116
|
+
if (result.status === 'fulfilled') {
|
|
117
|
+
console.log(`任务 ${index + 1}: 成功 - ${result.value}`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
console.log(`任务 ${index + 1}: 失败 - ${result.reason.message}`);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// 统计成功和失败的数量
|
|
124
|
+
const successCount = results.filter((r) => r.status === 'fulfilled').length;
|
|
125
|
+
const failureCount = results.filter((r) => r.status === 'rejected').length;
|
|
126
|
+
console.log(`\n成功: ${successCount} 个, 失败: ${failureCount} 个`);
|
|
127
|
+
}
|
|
128
|
+
// #endregion
|
|
129
|
+
// #region 示例4: Promise.race - 返回最快完成的 Promise
|
|
130
|
+
/**
|
|
131
|
+
* Promise.race 返回最快完成的 Promise(无论成功还是失败)
|
|
132
|
+
*/
|
|
133
|
+
async function promiseRaceDemo() {
|
|
134
|
+
console.log('\n=== Promise.race 示例 ===\n');
|
|
135
|
+
function fetchWithDelay(id, delay) {
|
|
136
|
+
return new Promise((resolve) => {
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
console.log(`任务 ${id} 完成 (延迟 ${delay}ms)`);
|
|
139
|
+
resolve(`任务 ${id} 的结果`);
|
|
140
|
+
}, delay);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
console.log('开始竞速...\n');
|
|
144
|
+
const winner = await Promise.race([
|
|
145
|
+
fetchWithDelay(1, 2000),
|
|
146
|
+
fetchWithDelay(2, 1000),
|
|
147
|
+
fetchWithDelay(3, 1500),
|
|
148
|
+
]);
|
|
149
|
+
console.log('\n最快完成的任务:', winner);
|
|
150
|
+
}
|
|
151
|
+
// #endregion
|
|
152
|
+
// #region 示例5: Promise.race 实现超时控制
|
|
153
|
+
/**
|
|
154
|
+
* 使用 Promise.race 实现请求超时控制
|
|
155
|
+
*/
|
|
156
|
+
async function timeoutControl() {
|
|
157
|
+
console.log('\n=== 使用 Promise.race 实现超时控制 ===\n');
|
|
158
|
+
// 创建超时 Promise
|
|
159
|
+
function timeout(ms) {
|
|
160
|
+
return new Promise((_, reject) => {
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
reject(new Error(`请求超时 (${ms}ms)`));
|
|
163
|
+
}, ms);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// 模拟慢速请求
|
|
167
|
+
function slowRequest() {
|
|
168
|
+
return new Promise((resolve) => {
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
resolve('请求成功');
|
|
171
|
+
}, 3000);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
console.log('发起请求(超时时间 2 秒)...\n');
|
|
176
|
+
const result = await Promise.race([
|
|
177
|
+
slowRequest(),
|
|
178
|
+
timeout(2000),
|
|
179
|
+
]);
|
|
180
|
+
console.log('结果:', result);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
if (error instanceof Error) {
|
|
184
|
+
console.error('错误:', error.message);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// #endregion
|
|
189
|
+
// #region 示例6: Promise.any - 返回第一个成功的 Promise
|
|
190
|
+
/**
|
|
191
|
+
* Promise.any 返回第一个成功的 Promise,所有都失败才失败
|
|
192
|
+
* Node.js >= 15.0.0
|
|
193
|
+
*/
|
|
194
|
+
async function promiseAnyDemo() {
|
|
195
|
+
console.log('\n=== Promise.any 示例 ===\n');
|
|
196
|
+
function fetchFromServer(serverId, delay, shouldFail) {
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
setTimeout(() => {
|
|
199
|
+
if (shouldFail) {
|
|
200
|
+
console.log(`服务器 ${serverId} 失败`);
|
|
201
|
+
reject(new Error(`服务器 ${serverId} 不可用`));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log(`服务器 ${serverId} 成功`);
|
|
205
|
+
resolve(`来自服务器 ${serverId} 的数据`);
|
|
206
|
+
}
|
|
207
|
+
}, delay);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
console.log('尝试从多个服务器获取数据...\n');
|
|
212
|
+
// 模拟从多个服务器获取数据,只要有一个成功就返回
|
|
213
|
+
const result = await Promise.any([
|
|
214
|
+
fetchFromServer(1, 2000, true), // 失败
|
|
215
|
+
fetchFromServer(2, 1500, false), // 成功
|
|
216
|
+
fetchFromServer(3, 1000, true), // 失败
|
|
217
|
+
]);
|
|
218
|
+
console.log('\n获取成功:', result);
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
console.error('所有服务器都失败了:', error);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// #endregion
|
|
225
|
+
// #region 示例7: 并发控制对比
|
|
226
|
+
/**
|
|
227
|
+
* 对比不同并发控制方法的行为
|
|
228
|
+
*/
|
|
229
|
+
async function comparePromiseMethods() {
|
|
230
|
+
console.log('\n=== 并发控制方法对比 ===\n');
|
|
231
|
+
function task(id, delay, shouldFail) {
|
|
232
|
+
return new Promise((resolve, reject) => {
|
|
233
|
+
setTimeout(() => {
|
|
234
|
+
if (shouldFail) {
|
|
235
|
+
reject(new Error(`任务 ${id} 失败`));
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
resolve(`任务 ${id} 成功`);
|
|
239
|
+
}
|
|
240
|
+
}, delay);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
const tasks = [
|
|
244
|
+
task(1, 1000, false),
|
|
245
|
+
task(2, 1500, true),
|
|
246
|
+
task(3, 500, false),
|
|
247
|
+
];
|
|
248
|
+
console.log('Promise.all: 所有成功才成功,一个失败就失败');
|
|
249
|
+
console.log('Promise.allSettled: 等待所有完成,返回每个状态');
|
|
250
|
+
console.log('Promise.race: 返回最快完成的(成功或失败)');
|
|
251
|
+
console.log('Promise.any: 返回第一个成功的,所有失败才失败\n');
|
|
252
|
+
// 注意:这里为了演示,我们需要重新创建 tasks
|
|
253
|
+
console.log('--- Promise.allSettled 结果 ---');
|
|
254
|
+
const settledResults = await Promise.allSettled([
|
|
255
|
+
task(1, 1000, false),
|
|
256
|
+
task(2, 1500, true),
|
|
257
|
+
task(3, 500, false),
|
|
258
|
+
]);
|
|
259
|
+
console.log(settledResults.map((r, i) => `任务${i + 1}: ${r.status}`));
|
|
260
|
+
console.log('\n--- Promise.race 结果 ---');
|
|
261
|
+
try {
|
|
262
|
+
const raceResult = await Promise.race([
|
|
263
|
+
task(1, 1000, false),
|
|
264
|
+
task(2, 1500, true),
|
|
265
|
+
task(3, 500, false),
|
|
266
|
+
]);
|
|
267
|
+
console.log('最快完成:', raceResult);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
if (error instanceof Error) {
|
|
271
|
+
console.log('最快完成(失败):', error.message);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// #endregion
|
|
276
|
+
// 主函数:根据参数运行指定示例
|
|
277
|
+
if (require.main === module) {
|
|
278
|
+
const exampleNumber = process.argv[2];
|
|
279
|
+
const examples = {
|
|
280
|
+
'1': promiseAllDemo,
|
|
281
|
+
'2': promiseAllWithFailure,
|
|
282
|
+
'3': promiseAllSettledDemo,
|
|
283
|
+
'4': promiseRaceDemo,
|
|
284
|
+
'5': timeoutControl,
|
|
285
|
+
'6': promiseAnyDemo,
|
|
286
|
+
'7': comparePromiseMethods,
|
|
287
|
+
};
|
|
288
|
+
if (exampleNumber && examples[exampleNumber]) {
|
|
289
|
+
console.log(`\n运行示例 ${exampleNumber}:\n`);
|
|
290
|
+
examples[exampleNumber]().catch(console.error);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
console.log('请指定要运行的示例编号 (1-7)');
|
|
294
|
+
console.log('例如: ts-node src/demo/promise-async/02-并发控制.ts 1');
|
|
295
|
+
console.log('\n可用示例:');
|
|
296
|
+
console.log('1 - Promise.all 基础用法');
|
|
297
|
+
console.log('2 - Promise.all 失败处理');
|
|
298
|
+
console.log('3 - Promise.allSettled 用法');
|
|
299
|
+
console.log('4 - Promise.race 基础用法');
|
|
300
|
+
console.log('5 - Promise.race 实现超时控制');
|
|
301
|
+
console.log('6 - Promise.any 用法');
|
|
302
|
+
console.log('7 - 并发控制方法对比');
|
|
303
|
+
}
|
|
304
|
+
}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Promise 与 async/await 高级模式
|
|
4
|
+
* ===============================
|
|
5
|
+
* 本文件介绍 Promise 的高级使用模式:串行执行、并发限制、重试机制等
|
|
6
|
+
* 适用于 Node.js >= 14.0.0
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.serialExecution = serialExecution;
|
|
10
|
+
exports.serialWithReduce = serialWithReduce;
|
|
11
|
+
exports.concurrencyLimit = concurrencyLimit;
|
|
12
|
+
exports.retryMechanism = retryMechanism;
|
|
13
|
+
exports.promiseCache = promiseCache;
|
|
14
|
+
exports.lazyPromise = lazyPromise;
|
|
15
|
+
exports.promiseQueue = promiseQueue;
|
|
16
|
+
// #region 示例1: 串行执行多个异步任务
|
|
17
|
+
/**
|
|
18
|
+
* 使用 async/await 串行执行多个异步任务
|
|
19
|
+
*/
|
|
20
|
+
async function serialExecution() {
|
|
21
|
+
console.log('=== 串行执行异步任务 ===\n');
|
|
22
|
+
function processTask(id) {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
const delay = 1000;
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
console.log(`任务 ${id} 完成`);
|
|
27
|
+
resolve(`任务 ${id} 的结果`);
|
|
28
|
+
}, delay);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
console.log('开始串行执行...\n');
|
|
32
|
+
const startTime = Date.now();
|
|
33
|
+
const results = [];
|
|
34
|
+
for (let i = 1; i <= 3; i++) {
|
|
35
|
+
const result = await processTask(i);
|
|
36
|
+
results.push(result);
|
|
37
|
+
}
|
|
38
|
+
const endTime = Date.now();
|
|
39
|
+
console.log('\n所有结果:', results);
|
|
40
|
+
console.log(`总耗时: ${endTime - startTime}ms (约 3 秒)`);
|
|
41
|
+
}
|
|
42
|
+
// #endregion
|
|
43
|
+
// #region 示例2: 使用 reduce 实现串行执行
|
|
44
|
+
/**
|
|
45
|
+
* 使用 reduce 优雅地实现串行执行
|
|
46
|
+
*/
|
|
47
|
+
async function serialWithReduce() {
|
|
48
|
+
console.log('\n=== 使用 reduce 串行执行 ===\n');
|
|
49
|
+
function fetchData(id) {
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
console.log(`获取数据 ${id}`);
|
|
53
|
+
resolve(id * 10);
|
|
54
|
+
}, 500);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const ids = [1, 2, 3, 4, 5];
|
|
58
|
+
const results = await ids.reduce(async (previousPromise, id) => {
|
|
59
|
+
const acc = await previousPromise;
|
|
60
|
+
const result = await fetchData(id);
|
|
61
|
+
return [...acc, result];
|
|
62
|
+
}, Promise.resolve([]));
|
|
63
|
+
console.log('\n最终结果:', results);
|
|
64
|
+
}
|
|
65
|
+
// #endregion
|
|
66
|
+
// #region 示例3: 并发限制(控制同时执行的任务数量)
|
|
67
|
+
/**
|
|
68
|
+
* 实现并发限制,控制同时执行的 Promise 数量
|
|
69
|
+
*/
|
|
70
|
+
async function concurrencyLimit() {
|
|
71
|
+
console.log('\n=== 并发限制 ===\n');
|
|
72
|
+
function task(id) {
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
const delay = Math.random() * 1000 + 500;
|
|
75
|
+
console.log(`任务 ${id} 开始 (预计 ${delay.toFixed(0)}ms)`);
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
console.log(`任务 ${id} 完成`);
|
|
78
|
+
resolve(`任务 ${id} 的结果`);
|
|
79
|
+
}, delay);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// 并发限制函数
|
|
83
|
+
async function runWithLimit(tasks, limit) {
|
|
84
|
+
const results = [];
|
|
85
|
+
const executing = [];
|
|
86
|
+
for (const taskFn of tasks) {
|
|
87
|
+
const promise = taskFn().then((result) => {
|
|
88
|
+
results.push(result);
|
|
89
|
+
executing.splice(executing.indexOf(promise), 1);
|
|
90
|
+
});
|
|
91
|
+
executing.push(promise);
|
|
92
|
+
if (executing.length >= limit) {
|
|
93
|
+
await Promise.race(executing);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
await Promise.all(executing);
|
|
97
|
+
return results;
|
|
98
|
+
}
|
|
99
|
+
// 创建 10 个任务,但限制同时只能执行 3 个
|
|
100
|
+
const tasks = Array.from({ length: 10 }, (_, i) => () => task(i + 1));
|
|
101
|
+
console.log('开始执行 10 个任务,并发限制为 3\n');
|
|
102
|
+
const startTime = Date.now();
|
|
103
|
+
const results = await runWithLimit(tasks, 3);
|
|
104
|
+
const endTime = Date.now();
|
|
105
|
+
console.log(`\n完成 ${results.length} 个任务,总耗时: ${endTime - startTime}ms`);
|
|
106
|
+
}
|
|
107
|
+
// #endregion
|
|
108
|
+
// #region 示例4: 重试机制
|
|
109
|
+
/**
|
|
110
|
+
* 实现带重试机制的异步操作
|
|
111
|
+
*/
|
|
112
|
+
async function retryMechanism() {
|
|
113
|
+
console.log('\n=== 重试机制 ===\n');
|
|
114
|
+
let attemptCount = 0;
|
|
115
|
+
// 模拟可能失败的操作
|
|
116
|
+
function unreliableOperation() {
|
|
117
|
+
attemptCount++;
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
setTimeout(() => {
|
|
120
|
+
// 前两次失败,第三次成功
|
|
121
|
+
if (attemptCount < 3) {
|
|
122
|
+
console.log(`第 ${attemptCount} 次尝试失败`);
|
|
123
|
+
reject(new Error('操作失败'));
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
console.log(`第 ${attemptCount} 次尝试成功`);
|
|
127
|
+
resolve('操作成功');
|
|
128
|
+
}
|
|
129
|
+
}, 500);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// 重试函数
|
|
133
|
+
async function retry(fn, maxRetries, delay = 1000) {
|
|
134
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
135
|
+
try {
|
|
136
|
+
return await fn();
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (i === maxRetries - 1) {
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
console.log(`等待 ${delay}ms 后重试...\n`);
|
|
143
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
throw new Error('不应该到达这里');
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
console.log('开始执行不可靠的操作(最多重试 3 次)\n');
|
|
150
|
+
const result = await retry(unreliableOperation, 3, 1000);
|
|
151
|
+
console.log('\n最终结果:', result);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (error instanceof Error) {
|
|
155
|
+
console.error('所有重试都失败了:', error.message);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// #endregion
|
|
160
|
+
// #region 示例5: Promise 缓存
|
|
161
|
+
/**
|
|
162
|
+
* 实现 Promise 结果缓存,避免重复请求
|
|
163
|
+
*/
|
|
164
|
+
async function promiseCache() {
|
|
165
|
+
console.log('\n=== Promise 缓存 ===\n');
|
|
166
|
+
const cache = new Map();
|
|
167
|
+
function fetchWithCache(key, fetcher) {
|
|
168
|
+
if (cache.has(key)) {
|
|
169
|
+
console.log(`从缓存获取: ${key}`);
|
|
170
|
+
return cache.get(key);
|
|
171
|
+
}
|
|
172
|
+
console.log(`首次请求: ${key}`);
|
|
173
|
+
const promise = fetcher();
|
|
174
|
+
cache.set(key, promise);
|
|
175
|
+
// 如果请求失败,从缓存中移除
|
|
176
|
+
promise.catch(() => {
|
|
177
|
+
cache.delete(key);
|
|
178
|
+
});
|
|
179
|
+
return promise;
|
|
180
|
+
}
|
|
181
|
+
// 模拟数据获取
|
|
182
|
+
function fetchUser(id) {
|
|
183
|
+
return new Promise((resolve) => {
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
resolve({ id, name: `用户${id}` });
|
|
186
|
+
}, 1000);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
// 多次请求同一个用户
|
|
190
|
+
console.log('发起 3 次相同的请求...\n');
|
|
191
|
+
const [user1, user2, user3] = await Promise.all([
|
|
192
|
+
fetchWithCache('user-1', () => fetchUser(1)),
|
|
193
|
+
fetchWithCache('user-1', () => fetchUser(1)),
|
|
194
|
+
fetchWithCache('user-1', () => fetchUser(1)),
|
|
195
|
+
]);
|
|
196
|
+
console.log('\n结果:', user1, user2, user3);
|
|
197
|
+
console.log('注意:虽然发起了 3 次请求,但实际只执行了 1 次');
|
|
198
|
+
}
|
|
199
|
+
// #endregion
|
|
200
|
+
// #region 示例6: 延迟执行(Lazy Promise)
|
|
201
|
+
/**
|
|
202
|
+
* 创建延迟执行的 Promise(只有在需要时才执行)
|
|
203
|
+
*/
|
|
204
|
+
async function lazyPromise() {
|
|
205
|
+
console.log('\n=== 延迟执行的 Promise ===\n');
|
|
206
|
+
// 普通 Promise 会立即执行
|
|
207
|
+
console.log('创建普通 Promise:');
|
|
208
|
+
const eagerPromise = new Promise((resolve) => {
|
|
209
|
+
console.log(' 立即执行!');
|
|
210
|
+
resolve('结果');
|
|
211
|
+
});
|
|
212
|
+
// 延迟 Promise 只有在调用时才执行
|
|
213
|
+
console.log('\n创建延迟 Promise:');
|
|
214
|
+
const lazyPromiseFactory = () => new Promise((resolve) => {
|
|
215
|
+
console.log(' 现在才执行!');
|
|
216
|
+
resolve('结果');
|
|
217
|
+
});
|
|
218
|
+
console.log('延迟 Promise 已创建,但还没执行');
|
|
219
|
+
console.log('等待 2 秒...\n');
|
|
220
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
221
|
+
console.log('现在调用延迟 Promise:');
|
|
222
|
+
await lazyPromiseFactory();
|
|
223
|
+
}
|
|
224
|
+
// #endregion
|
|
225
|
+
// #region 示例7: Promise 队列
|
|
226
|
+
/**
|
|
227
|
+
* 实现 Promise 队列,按顺序执行任务
|
|
228
|
+
*/
|
|
229
|
+
async function promiseQueue() {
|
|
230
|
+
console.log('\n=== Promise 队列 ===\n');
|
|
231
|
+
class PromiseQueue {
|
|
232
|
+
constructor() {
|
|
233
|
+
this.queue = [];
|
|
234
|
+
this.running = false;
|
|
235
|
+
}
|
|
236
|
+
add(task) {
|
|
237
|
+
return new Promise((resolve, reject) => {
|
|
238
|
+
this.queue.push(async () => {
|
|
239
|
+
try {
|
|
240
|
+
const result = await task();
|
|
241
|
+
resolve(result);
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
reject(error);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
if (!this.running) {
|
|
248
|
+
this.run();
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
async run() {
|
|
253
|
+
this.running = true;
|
|
254
|
+
while (this.queue.length > 0) {
|
|
255
|
+
const task = this.queue.shift();
|
|
256
|
+
await task();
|
|
257
|
+
}
|
|
258
|
+
this.running = false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const queue = new PromiseQueue();
|
|
262
|
+
function task(id, delay) {
|
|
263
|
+
return new Promise((resolve) => {
|
|
264
|
+
console.log(`任务 ${id} 开始`);
|
|
265
|
+
setTimeout(() => {
|
|
266
|
+
console.log(`任务 ${id} 完成 (耗时 ${delay}ms)`);
|
|
267
|
+
resolve(`任务 ${id} 的结果`);
|
|
268
|
+
}, delay);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
console.log('添加 5 个任务到队列\n');
|
|
272
|
+
// 同时添加多个任务,但它们会按顺序执行
|
|
273
|
+
const results = await Promise.all([
|
|
274
|
+
queue.add(() => task(1, 1000)),
|
|
275
|
+
queue.add(() => task(2, 500)),
|
|
276
|
+
queue.add(() => task(3, 800)),
|
|
277
|
+
queue.add(() => task(4, 300)),
|
|
278
|
+
queue.add(() => task(5, 600)),
|
|
279
|
+
]);
|
|
280
|
+
console.log('\n所有任务完成:', results);
|
|
281
|
+
}
|
|
282
|
+
// #endregion
|
|
283
|
+
// 主函数:根据参数运行指定示例
|
|
284
|
+
if (require.main === module) {
|
|
285
|
+
const exampleNumber = process.argv[2];
|
|
286
|
+
const examples = {
|
|
287
|
+
'1': serialExecution,
|
|
288
|
+
'2': serialWithReduce,
|
|
289
|
+
'3': concurrencyLimit,
|
|
290
|
+
'4': retryMechanism,
|
|
291
|
+
'5': promiseCache,
|
|
292
|
+
'6': lazyPromise,
|
|
293
|
+
'7': promiseQueue,
|
|
294
|
+
};
|
|
295
|
+
if (exampleNumber && examples[exampleNumber]) {
|
|
296
|
+
console.log(`\n运行示例 ${exampleNumber}:\n`);
|
|
297
|
+
examples[exampleNumber]().catch(console.error);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
console.log('请指定要运行的示例编号 (1-7)');
|
|
301
|
+
console.log('例如: ts-node src/demo/promise-async/03-高级模式.ts 1');
|
|
302
|
+
console.log('\n可用示例:');
|
|
303
|
+
console.log('1 - 串行执行异步任务');
|
|
304
|
+
console.log('2 - 使用 reduce 串行执行');
|
|
305
|
+
console.log('3 - 并发限制');
|
|
306
|
+
console.log('4 - 重试机制');
|
|
307
|
+
console.log('5 - Promise 缓存');
|
|
308
|
+
console.log('6 - 延迟执行的 Promise');
|
|
309
|
+
console.log('7 - Promise 队列');
|
|
310
|
+
}
|
|
311
|
+
}
|