You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript:如何确保所有Promise处于已敲定状态?代码正确性咨询

问题分析与解决方案

你的代码核心问题

你写的while (!finishWaiting)是同步死循环,会完全阻塞JavaScript的事件循环。因为JS是单线程的,同步代码执行时,微任务队列(比如Promise的then回调)根本没有机会被处理。也就是说allPromises.then里的finishWaiting = true永远不会执行,代码会一直卡在这个循环里,页面直接卡死。

正确实现方式

你需要利用Promise的异步特性等待所有结果,而非用同步循环阻塞线程。以下分两种场景给出方案:

方案一:改为async/await函数(最简洁推荐)

如果允许把函数改成async函数,代码会非常直观:

async function yourFunction() {
    let promisesToWait = [];
    // 存储所有结果的数组
    let results = [];

    for (let constraintIndex = 0; constraintIndex < constraintsArray.length; constraintIndex++) {
        let curConstraints = constraintsArray[constraintIndex];
        let curPromise = navigator.mediaDevices.getUserMedia(curConstraints)
            .then(stream => {
                // 处理resolve逻辑
                return { status: 'fulfilled', value: stream };
            })
            .catch(err => {
                // 处理reject逻辑
                return { status: 'rejected', reason: err };
            });
        promisesToWait.push(curPromise);
    }

    // 等待所有Promise敲定
    let allResults = await Promise.allSettled(promisesToWait);
    
    // 对应你代码的C点,在这里处理所有结果
    allResults.forEach(result => {
        if (result.status === 'fulfilled') {
            // 处理成功的stream
            console.log('成功获取流:', result.value);
        } else {
            // 处理失败的情况
            console.log('获取流失败:', result.reason);
        }
    });

    // 可在此return结果,函数会返回一个Promise
    return allResults;
}

方案二:保持非async函数,用Promise回调处理后续逻辑

如果必须保持函数是非async的,所有需要在Promise敲定后执行的逻辑(结果收集、return相关处理)都要放到Promise.allSettled的then回调里:

function yourFunction() {
    let promisesToWait = [];

    for (let constraintIndex = 0; constraintIndex < constraintsArray.length; constraintIndex++) {
        let curConstraints = constraintsArray[constraintIndex];
        let curPromise = navigator.mediaDevices.getUserMedia(curConstraints);
        promisesToWait.push(curPromise);
    }

    // 等待所有Promise敲定后处理结果
    Promise.allSettled(promisesToWait).then(allResults => {
        // 对应你代码的C点,在这里处理所有结果
        allResults.forEach(result => {
            if (result.status === 'fulfilled') {
                // 处理成功的stream
                console.log('成功获取流:', result.value);
            } else {
                // 处理失败的情况
                console.log('获取流失败:', result.reason);
            }
        });

        // 如果需要向外部传递结果,可使用回调函数
        // 例如:callback(allResults);
    });

    // 非async函数在此return无法返回Promise结果,只能提前返回
    // 若需获取结果,必须通过回调或让函数返回Promise(本质和async函数一致)
}

补充说明

  • 你之前在每个curPromise上单独绑定then和catch是可行的,但用Promise.allSettled统一收集所有结果会更高效,它会返回所有Promise的敲定状态(成功/失败)。
  • 永远不要用同步循环等待异步操作,这会彻底阻塞JS线程,导致页面无响应。异步操作的等待必须用Promise的then或await实现。

内容的提问来源于stack exchange,提问作者user19309573

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:54:50