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

Node.js中await调用导致procsseddocs出现重复订单ID问题排查

问题:MongoDB异步处理导致procsseddocs数组出现重复订单ID

在这段Node.js代码中,main函数从MongoDB的order集合获取数据,当businessSubType为FlightBooking时调用flightBookingTransform处理。initialDocs2中存入的是唯一的订单ID,但procsseddocs数组却出现了重复值,请问原因是什么?

const { MongoClient } = require('mongodb');
initialDocs2 = []
procsseddocs = []
txnarr = []
async function main() {
    const url = "<connectionstring>"
    const client = new MongoClient(url);
    let target_db = "<db>"

    totalDocCount = 0;
    cabCount = 0;
    dutyFreeCount = 0;
    flightBookingCount = 0;
    pranaamCount = 0;
    try {
        await client.connect();
        target_db = client.db(target_db);
        initialdocs = []
        await target_db.collection("order").find().forEach(async function (doc) {
            totalDocCount++;
            if (doc._id) {
                if (doc.businessSubType == "FlightBooking") {
                    flightBookingCount++;
                    try {
                        initialdocs.push(String(doc._id))
                        flightBookingTransform(target_db, doc);
                    } catch (e) {
                        console.log("Errored in flight booking free transform:", doc._id, " error:", e)
                    }
                }
            }
        }
        )
    }
    catch (e) {
        console.error(e);
    }
    finally {
        await client.close();
    }
}
async function flightBookingTransform(target_db, docOrder) {
    try {
        orderIdString = String(docOrder._id)
        initialDocs2.push(orderIdString)
        docTransactionarr = await target_db.collection("transaction").find({
            "orderId.oid": orderIdString
        }).sort({
            "_id": -1
        }).limit(1).toArray()

        if (docTransactionarr && docTransactionarr.length > 0)
            docTransaction = docTransactionarr[0]
        else
            return
        txnarr.push(String(docTransaction._id))
        procsseddocs.push(orderIdString)
    } catch (e) {
        console.log("Something went wrong", e)
    }
};
main()

问题原因

1. 核心原因:全局变量被并发异步操作覆盖

flightBookingTransform函数中的orderIdString、docTransactionarr、docTransaction均未用let/const声明,默认成为全局变量。当多个flightBookingTransform因为forEach的异步回调并发执行时,这些全局变量会被后续调用覆盖:

  • 第一个调用进入await查询transaction的等待阶段时,第二个调用会修改orderIdString为新的订单ID
  • 第一个调用的await完成后,使用的已经是被覆盖后的orderIdString,导致错误的订单ID被重复推入procsseddocs

2. 次要原因:forEach无法等待异步回调

MongoDB的find().forEach()不支持等待异步回调完成,await target_db.collection("order").find().forEach(...)并不会等待所有异步回调执行完毕。这会导致大量flightBookingTransform并发执行,既加剧了全局变量被覆盖的概率,还可能在所有处理完成前就执行client.close(),导致部分数据库查询失败。


修复方案

1. 使用块级作用域变量

给flightBookingTransform中的所有变量添加let/const声明,避免全局变量污染:

async function flightBookingTransform(target_db, docOrder) {
    try {
        const orderIdString = String(docOrder._id);
        initialDocs2.push(orderIdString);
        const docTransactionarr = await target_db.collection("transaction").find({
            "orderId.oid": orderIdString
        }).sort({
            "_id": -1
        }).limit(1).toArray();

        if (docTransactionarr && docTransactionarr.length > 0) {
            const docTransaction = docTransactionarr[0];
            txnarr.push(String(docTransaction._id));
            procsseddocs.push(orderIdString);
        } else {
            return;
        }
    } catch (e) {
        console.log("Something went wrong", e);
    }
};

2. 替换forEach为可等待的遍历方式

改用for...of遍历查询结果,确保每个flightBookingTransform执行完成后再处理下一个文档:

// 替换main函数中的forEach代码块
const cursor = target_db.collection("order").find();
for await (const doc of cursor) {
    totalDocCount++;
    if (doc._id) {
        if (doc.businessSubType == "FlightBooking") {
            flightBookingCount++;
            try {
                initialdocs.push(String(doc._id));
                await flightBookingTransform(target_db, doc);
            } catch (e) {
                console.log("Errored in flight booking free transform:", doc._id, " error:", e);
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:10:07