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

for循环忽略Mongoose await调用,数据库操作未完成就关闭服务器

问题分析与解决方案

核心问题

你的代码里model.collection.findOne用了回调函数模式,外层for循环不会等待回调内的异步操作(await model.save()/findOneAndUpdate)完成,直接跳到closeServer()执行,导致数据还没处理完服务器就关闭了。另外,回调里的async函数不会影响外层for循环的执行流程,因为for循环是同步遍历的。

修正方案

改用Mongoose的Promise风格API,把每一次的数据对比、新增/更新操作包装成Promise,让for循环等待每个操作完成,或者收集所有Promise后统一等待:

方案1:串行执行(按顺序处理每条数据)

async function comparedata(length) {
    console.log("Starting comparing entries in data");
    // 遍历每条数据,用await等待当前条目的所有异步操作完成再处理下一条
    for (let x = 0; x < length; x++) {
        const link = dataLinks[x];
        const gameName = dataGames[x].replace('Download', ' ');
        const logo = dataLogos[x];

        try {
            // 改用Promise版findOne,不用回调
            const found = await dataModel.findOne({ "link": link });
            
            if (!found) {
                // 新增条目
                const model = new dataModel({
                    link,
                    name: gameName,
                    logo,
                    provider: 'data',
                });
                const result = await model.save();
                console.log(result);
            } else {
                // 检查是否需要更新名称
                if (dataGames[x] !== found.name) {
                    await dataModel.findOneAndUpdate(
                        { link },
                        { "$set": { "name": dataGames[x] } }
                    );
                }
            }
        } catch (err) {
            console.error('处理数据出错:', err);
        }
    }
    // 所有数据处理完成后再关闭服务器
    closeServer();
}

方案2:并行执行(同时处理所有数据,效率更高)

如果数据量不大,可用Promise.all并行处理所有条目,提升速度:

async function comparedata(length) {
    console.log("Starting comparing entries in data");
    // 生成所有处理数据的Promise数组
    const promises = [];
    for (let x = 0; x < length; x++) {
        const link = dataLinks[x];
        const gameName = dataGames[x].replace('Download', ' ');
        const logo = dataLogos[x];

        // 把每条数据的处理逻辑包装成Promise
        const task = async () => {
            try {
                const found = await dataModel.findOne({ "link": link });
                if (!found) {
                    const model = new dataModel({
                        link,
                        name: gameName,
                        logo,
                        provider: 'data',
                    });
                    const result = await model.save();
                    console.log(result);
                } else {
                    if (dataGames[x] !== found.name) {
                        await dataModel.findOneAndUpdate(
                            { link },
                            { "$set": { "name": dataGames[x] } }
                        );
                    }
                }
            } catch (err) {
                console.error('处理数据出错:', err);
            }
        };
        promises.push(task());
    }
    // 等待所有Promise完成后再关闭服务器
    await Promise.all(promises);
    closeServer();
}

关键改动点

  • 抛弃回调式的findOne,改用Mongoose原生支持的Promise版本,配合await等待异步操作完成。
  • 把每条数据的处理逻辑放在async函数里,确保await能正确阻塞当前流程(串行方案),或者收集所有Promise统一等待(并行方案)。
  • 所有异步操作完成后,再调用closeServer()。

为什么之前的Promise尝试失败?

大概率是你没有正确把findOne的回调逻辑包装成Promise,或者没有等待所有异步任务的Promise完成就调用了closeServer()。比如只是简单把回调包成Promise但没在for循环里用await,或者没把所有任务的Promise放进数组用Promise.all等待,都会导致服务器提前关闭。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:20:27