策略
- 并发控制:使用队列或信号量机制来限制并发请求的数量,确保不会同时发起过多请求耗尽资源。
- 任务编排:对于需要顺序执行的异步操作,使用
async/await
或 Promise.then()
链式调用实现顺序执行。对于并发执行的异步操作,使用 Promise.all()
或 Promise.race()
进行处理。
技术手段
async/await
:它是基于 Promise
的语法糖,使异步代码看起来像同步代码,提高代码可读性。
Promise.all()
:用于并行执行多个 Promise
,当所有 Promise
都 resolved 时返回一个 resolved 的 Promise
,当其中任何一个 Promise
被 rejected 时返回一个 rejected 的 Promise
。
Promise.race()
:同样并行执行多个 Promise
,但只要其中一个 Promise
被 resolved 或 rejected,就返回该 Promise
的结果。
- 队列实现并发控制:可以通过自定义队列,将异步任务按顺序放入队列,每次从队列中取出一定数量的任务并发执行,完成后再从队列中取出新的任务执行。
关键部分示例实现
顺序执行异步操作
async function sequentialOperations() {
const result1 = await asyncOperation1();
const result2 = await asyncOperation2(result1);
const result3 = await asyncOperation3(result2);
return result3;
}
async function asyncOperation1(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Operation 1 result');
}, 1000);
});
}
async function asyncOperation2(input: string): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`${input}, Operation 2 result`);
}, 1000);
});
}
async function asyncOperation3(input: string): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`${input}, Operation 3 result`);
}, 1000);
});
}
并发执行异步操作
async function concurrentOperations() {
const [result1, result2, result3] = await Promise.all([asyncOperation1(), asyncOperation2(), asyncOperation3()]);
return `${result1}, ${result2}, ${result3}`;
}
并发控制示例(使用队列)
class TaskQueue {
private tasks: (() => Promise<void>)[] = [];
private runningCount = 0;
private maxConcurrent: number;
constructor(maxConcurrent: number) {
this.maxConcurrent = maxConcurrent;
}
addTask(task: () => Promise<void>) {
this.tasks.push(task);
this.runNext();
}
private async runNext() {
while (this.runningCount < this.maxConcurrent && this.tasks.length > 0) {
const task = this.tasks.shift();
if (task) {
this.runningCount++;
try {
await task();
} finally {
this.runningCount--;
this.runNext();
}
}
}
}
}
// 使用示例
const queue = new TaskQueue(3); // 最大并发数为3
queue.addTask(() => asyncOperation1());
queue.addTask(() => asyncOperation2());
queue.addTask(() => asyncOperation3());