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

TypeScript异步异常:Promise未等待checkMarketplaceStatus执行完成

异步执行顺序异常问题排查与解决

问题场景

学习TypeScript并采用函数式编程,编写了从MongoDB查询文档后批量调用SQL Server获取数据的程序。将SQL Server数据获取逻辑封装在checkMarketplaceStatus异步函数中,主逻辑通过Promise.allSettled批量调用该函数后,后续then分支中data为undefined。调试发现checkMarketplaceStatus内的await未生效,函数未执行完成就进入后续分支,但单独执行SQL数据获取逻辑可正常返回预期数据。

相关代码

sql.ts代码

const dbConfig: sql.config = {
    driver: "msnodesqlv8",
    connectionString: 'Driver={ODBC Driver 17 for SQL Server};Server=server.com;Database=dbName;Trusted_Connection=yes;',
    options: {
        trustedConnection: true,
        encrypt: true,
        trustServerCertificate: true,
        
    }
}
async function sqlConnect(config: sql.config):Promise<sql.ConnectionPool>{
    let pool =  await sql.connect(config)
    return pool
}
async function createPreparedStatement(conn:sql.ConnectionPool,query, inputParams:string[]):Promise<sql.PreparedStatement>{
    const ps = await new sql.PreparedStatement(conn);
    ps.input('id',sql.NVarChar)
    await ps.prepare(query)
    return ps
}

async function executePreparedStatement(inputParams, ps: sql.PreparedStatement){
    const result = await ps.execute(inputParams)
    return result
}

checkMarketplaceStatus函数代码

async function checkMarketplaceStatus(item){

    let systemAssign = item["Id"]
    const connection:sql.ConnectionPool = await sqlConnect(dbConfig)
    const ps: sql.PreparedStatement = await createPreparedStatement(connection,
        "select Column_Name from Table_Name where Id = @id",
        ['id'])
    const data = await executePreparedStatement({id: systemAssign},ps)

    if (ps){
        await ps.unprepare();
    }
    return {mongoData: item, sqlData:data.recordset[0]}
}

主逻辑代码

...code to fetch document from mongo
}).then((data)=>{
       
    const promises = data.map( (item)=>{
         return checkMarketplaceStatus(item)   
    })
        
    return Promise.allSettled(promises)
        
}).then((data)=>{
    console.log(data) //-----data is undefined, NOT EXPECTED
})

问题分析

  1. createPreparedStatement中的错误await:new sql.PreparedStatement(conn)是同步构造函数,不需要加await,错误的await会破坏Promise链的执行顺序,导致后续异步操作异常。
  2. 未处理异步错误:checkMarketplaceStatus函数没有错误捕获逻辑,一旦SQL操作抛出异常,会导致Promise变为rejected状态,若Promise.allSettled处理不当,可能导致后续then接收异常结果。
  3. 连接泄漏风险:SQL连接使用后未主动关闭,可能导致连接池耗尽,间接影响异步流程的执行。

解决方案

1. 修正createPreparedStatement的同步构造

移除new sql.PreparedStatement(conn)前的await,确保构造逻辑正常:

async function createPreparedStatement(conn:sql.ConnectionPool,query, inputParams:string[]):Promise<sql.PreparedStatement>{
    const ps = new sql.PreparedStatement(conn); // 移除多余await
    ps.input('id',sql.NVarChar)
    await ps.prepare(query)
    return ps
}

2. 为checkMarketplaceStatus添加错误捕获与连接清理

确保函数无论成功失败都能返回明确结果,同时关闭SQL连接避免泄漏:

async function checkMarketplaceStatus(item){
    try {
        const systemAssign = item["Id"]
        const connection:sql.ConnectionPool = await sqlConnect(dbConfig)
        const ps: sql.PreparedStatement = await createPreparedStatement(connection,
            "select Column_Name from Table_Name where Id = @id",
            ['id'])
        const data = await executePreparedStatement({id: systemAssign},ps)

        if (ps) await ps.unprepare();
        await connection.close(); // 主动关闭连接
        return {mongoData: item, sqlData: data.recordset[0]}
    } catch (err) {
        // 捕获错误并返回明确的失败结果
        return {mongoData: item, error: err.message}
    }
}

3. 主逻辑中校验上游数据并处理结果

确认MongoDB返回的data是有效数组,同时正确处理Promise.allSettled的返回值:

// ...MongoDB查询代码
}).then((data)=>{
    // 校验MongoDB返回的数据有效性
    if (!Array.isArray(data) || data.length === 0) {
        console.warn('MongoDB未查询到有效数据');
        return [];
    }
    const promises = data.map(item => checkMarketplaceStatus(item))
    return Promise.allSettled(promises)
}).then((results)=>{
    console.log(results); // 现在会输出包含所有Promise结果的数组
    // 可按需拆分成功/失败结果
    const successful = results.filter(r => r.status === 'fulfilled').map(r => r.value);
    const failed = results.filter(r => r.status === 'rejected').map(r => r.reason);
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:42:41