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

语义解析器贪心Promise解析优先级调整及未完全解析提示实现问题

问题根因

你的问题和Promise执行优先级无关,属于架构设计的逻辑疏漏:
你所有可用于匹配的类型都来自传入parseElements的元素集合,当你遍历完所有元素、完成全部parseElement调用后,所有能被注册的类型就已经全部写入registredTypes。此时waitForTypes中剩余的监听对应的类型,就是当前批次永远无法命中的缺失类型,不会有后续逻辑触发它们的回调,对应的Promise会永远处于pending状态,不可能被resolve。

修复方案

我们只需要在所有元素遍历完成后,主动终止所有未命中的类型等待逻辑,再根据所有类型匹配的结果输出对应提示即可,修改点如下:

  1. 扩展事件类,新增缺失类型的终止逻辑,给等待中的Promise返回reject结果
  2. 解析完全部元素后,主动触发缺失类型的终止逻辑
  3. 使用Promise.allSettled替代Promise.all处理类型匹配结果,兼容部分类型匹配失败的场景
修改后的可运行代码
class Element{
    name = "";
    typeID = "";
    type = null;

    constructor(name, typeID){
        this.name = name;
        this.typeID = typeID;
    }
}

class Events{
    waitForTypes =  {};

    waitForType(typeName, cb){
        if(!this.waitForTypes[typeName]){
            this.waitForTypes[typeName] = [];
        }
        this.waitForTypes[typeName].push(cb);
    }
    triggerTypeFound(typeName){
        if(this.waitForTypes[typeName] && this.waitForTypes[typeName].length > 0){
            for(let cb of this.waitForTypes[typeName]){
                cb(null, this.registredTypes[typeName])
            }
            delete this.waitForTypes[typeName]
        }
    }
    // 新增:终止所有缺失类型的等待,返回错误
    failAllMissingTypes(){
        Object.keys(this.waitForTypes).forEach(typeName => {
            for(let cb of this.waitForTypes[typeName]){
                cb(new Error(`类型${typeName}不存在`), null)
            }
            delete this.waitForTypes[typeName]
        })
    }
}


class Parser extends Events{
    registredTypes = {}; // 原代码此处写为数组不合理,修正为对象
    typePromises = [];

    resolveType(element){
        console.log("resolve type: "+ element.name)
        this.registredTypes[element.name] = element;
        this.triggerTypeFound(element.name)
    }

    getType(typeId){
        if(this.registredTypes[typeId]){
            return Promise.resolve(this.registredTypes[typeId]);
        } else {
            return new Promise((resolve, reject) => {
                this.waitForType(typeId, (err, type) => {
                    if(err) return reject(err)
                    resolve(type)
                })
            });
        }
    }

    parseElement(element){
        console.log("parse Element " + element.name);
        this.resolveType(element);

        let typePromise = this.getType(element.typeID).then(type => {
            console.log("set Type for " + element.name);
            element.type = type
            return element
        });
        this.typePromises.push(typePromise)
    }

    parseElements(elements){
        for(let element of elements){
            this.parseElement(element);
        }
        // 所有元素解析完成后,直接终止所有未命中的类型等待
        this.failAllMissingTypes()
        console.log("parsing finished");
    }
}
测试逻辑

正常场景(所有类型可匹配)

let elements = [
    new Element("A", "B"),
    new Element("B", "B"),
    new Element("C", "B"),
];
let parser = new Parser()
parser.parseElements(elements)

Promise.allSettled(parser.typePromises).then(results => {
    const allSuccess = results.every(r => r.status === 'fulfilled')
    if(allSuccess){
        console.log("all types are resolved");
    } else {
        console.log("parsing finished, not all types are resolved");
    }
})

运行后会输出all types are resolved。

缺失类型场景

let elements = [
    new Element("A", "B")
];
let parser = new Parser()
parser.parseElements(elements)

Promise.allSettled(parser.typePromises).then(results => {
    const allSuccess = results.every(r => r.status === 'fulfilled')
    if(allSuccess){
        console.log("all types are resolved");
    } else {
        console.log("parsing finished, not all types are resolved");
    }
})

运行后会输出parsing finished, not all types are resolved。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 19:51:02