全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 7 分钟 ✍️ juanwangdev

JavaScript 并发控制

Promise 提供多种并发控制方法,用于管理多个异步任务的执行和结果处理。

Promise.all

JavaScript
// 所有 Promise 成功才返回,一个失败立即拒绝
const promises = [
    fetch('/api/user'),
    fetch('/api/posts'),
    fetch('/api/comments')
];

Promise.all(promises)
    .then(results => {
        // results 是数组,顺序对应 promises
        const [user, posts, comments] = results;
        console.log('全部成功:', user, posts, comments);
    })
    .catch(error => {
        // 任意一个失败,立即触发
        console.error('有失败:', error);
    });

// 空数组直接返回空数组
Promise.all([]).then(results => console.log(results));  // []

Promise.all 失败处理

JavaScript
// Promise.all 快速失败特性
const p1 = Promise.resolve('成功1');
const p2 = Promise.reject('失败');
const p3 = Promise.resolve('成功2');

Promise.all([p1, p2, p3])
    .then(results => console.log(results))
    .catch(error => console.log('第一个失败:', error));  // '失败'

// 不关心失败时使用 Promise.allSettled

// 或者包装每个 Promise 避免失败传播
const wrappedPromises = [p1, p2, p3].map(p =>
    p.catch(error => ({ status: 'failed', error }))
);

Promise.all(wrappedPromises)
    .then(results => console.log(results));
// [{ status: 'success', value: '成功1' }, { status: 'failed', error: '失败' }, ...]

Promise.race

JavaScript
// 返回最先完成的结果(无论成功或失败)
const promises = [
    new Promise(r => setTimeout(() => r('慢'), 1000)),
    new Promise(r => setTimeout(() => r('快'), 100)),
    new Promise((_, r) => setTimeout(() => r('失败'), 500))
];

Promise.race(promises)
    .then(result => console.log('最快成功:', result))   // '快'
    .catch(error => console.log('最快失败:', error));

// 实际应用:请求超时
function fetchWithTimeout(url, timeout = 5000) {
    const fetchPromise = fetch(url);
    const timeoutPromise = new Promise((_, reject) =>
        setTimeout(() => reject(new Error('请求超时')), timeout)
    );

    return Promise.race([fetchPromise, timeoutPromise]);
}

// 使用
fetchWithTimeout('/api/data', 3000)
    .then(response => response.json())
    .catch(error => console.log(error.message));  // 可能是"请求超时"

Promise.allSettled

JavaScript
// 等待所有 Promise 完成,返回每个的状态(ES2020)
const promises = [
    Promise.resolve('成功1'),
    Promise.reject('失败'),
    Promise.resolve('成功2')
];

Promise.allSettled(promises)
    .then(results => {
        results.forEach(result => {
            if (result.status === 'fulfilled') {
                console.log('成功:', result.value);
            } else {
                console.log('失败:', result.reason);
            }
        });
    });

// 输出:
// [{ status: 'fulfilled', value: '成功1' },
//  { status: 'rejected', reason: '失败' },
//  { status: 'fulfilled', value: '成功2' }]

Promise.any(ES2021)

JavaScript
// 等待第一个成功的 Promise,全部失败才拒绝
const promises = [
    Promise.reject('失败1'),
    Promise.resolve('成功'),
    Promise.reject('失败2')
];

Promise.any(promises)
    .then(result => console.log('第一个成功:', result))  // '成功'
    .catch(error => {
        // AggregateError:所有失败的集合
        console.log('全部失败:', error.errors);
    });

// 全部失败示例
Promise.any([
    Promise.reject('失败1'),
    Promise.reject('失败2')
]).catch(error => {
    console.log(error instanceof AggregateError);  // true
    console.log(error.errors);  // ['失败1', '失败2']
});

四种方法对比

方法成功条件失败条件返回值
Promise.all全部成功任一失败结果数组
Promise.race任一完成任一失败(最先)单个结果
Promise.allSettled无(永不失败)状态数组
Promise.any任一成功全部失败单个结果
JavaScript
// 选择指南:
// 1. 需要全部成功 → Promise.all
// 2. 需要最快结果 → Promise.race
// 3. 需要全部状态 → Promise.allSettled
// 4. 需要任一成功 → Promise.any

并发限制

JavaScript
// Promise.all 不限制并发数量,可能资源耗尽
// 实现并发限制

async function promiseLimit(tasks, limit = 3) {
    const results = [];
    const executing = new Set();

    for (const task of tasks) {
        const promise = Promise.resolve(task()).then(result => {
            executing.delete(promise);
            return result;
        });

        executing.add(promise);
        results.push(promise);

        if (executing.size >= limit) {
            await Promise.race(executing);
        }
    }

    return Promise.all(results);
}

// 使用:限制并发数为 3
const tasks = urls.map(url => () => fetch(url));
const results = await promiseLimit(tasks, 3);

// 更简洁的实现
class PromisePool {
    constructor(limit) {
        this.limit = limit;
        this.queue = [];
        this.active = 0;
    }

    async run(task) {
        while (this.active >= this.limit) {
            await new Promise(resolve => this.queue.push(resolve));
        }

        this.active++;
        try {
            return await task();
        } finally {
            this.active--;
            if (this.queue.length) {
                this.queue.shift()();
            }
        }
    }
}

// 使用
const pool = new PromisePool(5);
const results = await Promise.all(urls.map(url => pool.run(() => fetch(url))));

实际应用场景

JavaScript
// 并行请求多个接口
async function fetchAllData(userId) {
    const [user, posts, comments] = await Promise.all([
        fetch(`/api/user/${userId}`).then(r => r.json()),
        fetch(`/api/posts/${userId}`).then(r => r.json()),
        fetch(`/api/comments/${userId}`).then(r => r.json())
    ]);

    return { user, posts, comments };
}

// 批量上传,记录成功和失败
async function batchUpload(files) {
    const results = await Promise.allSettled(
        files.map(file => uploadFile(file))
    );

    const succeeded = results.filter(r => r.status === 'fulfilled');
    const failed = results.filter(r => r.status === 'rejected');

    console.log(`成功 ${succeeded.length},失败 ${failed.length}`);
    return { succeeded, failed };
}

// 多源备份,取最快成功的
async function fetchFromBackup(primary, backups) {
    return Promise.any([
        fetch(primary),
        ...backups.map(url => fetch(url))
    ]);
}

// 验证多个条件,全部满足
async function validateAll(conditions) {
    await Promise.all(conditions.map(check => check()));
    return true;  // 全部通过
}

注意事项

  • Promise.all 一个失败立即拒绝,不等待其他完成
  • Promise.race 返回最先完成的,可能是失败
  • Promise.allSettled 永不拒绝,适合记录全部状态
  • Promise.any 全部失败才拒绝,返回 AggregateError
JavaScript
// Promise.all 不等待失败后的 Promise
const slow = new Promise(r => setTimeout(() => r('慢'), 1000));
const fastFail = Promise.reject('快失败');

Promise.all([slow, fastFail])
    .catch(error => {
        console.log('失败:', error);  // 立即输出,不等 slow
        // slow 仍在执行,但结果被忽略
    });

// 如需等待全部完成,用 Promise.allSettled
Promise.allSettled([slow, fastFail])
    .then(results => {
        // 等待 slow 完成(1秒后)
        console.log(results);
    });

要点总结

  • Promise.all:全部成功才返回,一个失败立即拒绝
  • Promise.race:返回最先完成的结果(成功或失败)
  • Promise.allSettled:等待全部完成,返回状态数组(永不失败)
  • Promise.any:返回第一个成功,全部失败才拒绝(AggregateError)
  • 并发限制需手动实现(队列 + Promise.race)
  • 选择方法依据业务需求:全部成功、最快结果、全部状态、任一成功
  • Promise.all 不等待失败后的其他 Promise

📝 发现内容有误?点击此处直接编辑

← 上一篇 JavaScript 事件循环与微任务/宏任务
下一篇 → JavaScript 异步迭代器与 for await...of
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库