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

Node.js脚本使用Mongoose保存MongoDB文档后挂起问题排查

问题诊断与修复方案

核心问题定位

脚本完成职位ID保存循环后挂起,无法执行后续代码,结合代码和现象,问题出在两处:

  1. 重复关闭浏览器触发隐性错误:try块内已经执行了await browser.close(),但finally块又再次调用该方法,此时浏览器实例已销毁,会触发未被捕获的Promise拒绝,导致代码卡住。
  2. Mongoose连接配置不完整:mongoose.connect未传入必要的连接选项,可能导致连接状态不稳定,残留的连接事件阻塞脚本退出。

修复步骤

1. 移除重复的浏览器关闭操作

删除finally块中的await browser.close(),因为try块内已经完成了浏览器的关闭:

finally {
  await mongoose.connection.close();
  // 移除该行:await browser.close();
}

2. 完善Mongoose连接配置

为mongoose.connect添加标准连接选项,确保连接稳定建立与释放:

await mongoose.connect(`mongodb+srv:/xxxxxxxxx`, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

3. 优化数据库查询效率(可选)

原循环中每次调用findOne查询效率较低,可改为批量查询已存在的ID,减少数据库请求次数:

// 替换原循环逻辑
const existingVacancyIds = (await Vacancy.find({ vacancyId: { $in: vacanciesIds } })).map(v => v.vacancyId);
const newVacancies = vacanciesIds.filter(id => !existingVacancyIds.includes(id)).map(id => ({ vacancyId: id, active: true }));

if (newVacancies.length > 0) {
  await Vacancy.insertMany(newVacancies);
  console.log(`批量保存了 ${newVacancies.length} 个新职位ID`);
}

4. 添加全局错误捕获

在调用handler函数时添加错误捕获,避免未处理的Promise拒绝导致脚本静默挂起:

exports.handler().catch(err => {
  console.error("脚本执行出错:", err);
  process.exit(1);
});

修复后的完整代码片段

const puppeteer = require("puppeteer");
const mongoose = require("mongoose");
require("dotenv").config();

const vacancySchema = new mongoose.Schema({
  vacancyId: String,
  active: Boolean,
});
const Vacancy = mongoose.model("Vacancy", vacancySchema);

exports.handler = async () => {
  const browser = await puppeteer.launch({
    headless: true,
    defaultViewport: null,
  });

  const page = await browser.newPage();
  try {
    await page.goto("https:xxxxxxxxx");
    await page.waitForSelector("#vacancyTable");
    await page.select("select#dt-length-0", "100");
    let vacanciesIds = [];

    while (true) {
      let pageVacancies = await page.$$eval(
        "#vacancyTable tr > td.dt-type-numeric",
        (rows) => rows.map((row) => row.textContent.trim())
      );
      vacanciesIds = [...vacanciesIds, ...pageVacancies];

      const nextButtonClassList = await page.$eval(
        "[data-dt-idx='next']",
        (el) => Array.from(el.classList)
      );

      if (nextButtonClassList.includes("disabled")) break;

      const nextButton = await page.$("[data-dt-idx='next']");
      await nextButton.click();
      await page.waitForNetworkIdle();
    }

    await browser.close();

    await mongoose.connect(`mongodb+srv:/xxxxxxxxx`, {
      useNewUrlParser: true,
      useUnifiedTopology: true
    });

    // 批量查询优化
    const existingVacancyIds = (await Vacancy.find({ vacancyId: { $in: vacanciesIds } })).map(v => v.vacancyId);
    const newVacancies = vacanciesIds.filter(id => !existingVacancyIds.includes(id)).map(id => ({ vacancyId: id, active: true }));

    if (newVacancies.length > 0) {
      await Vacancy.insertMany(newVacancies);
      console.log(`批量保存了 ${newVacancies.length} 个新职位ID`);
    }

    console.log("Scrape check vs db finished");
  } catch (error) {
    console.log(error.message);
  } finally {
    await mongoose.connection.close();
  }
};

// 添加全局错误捕获
exports.handler().catch(err => {
  console.error("脚本执行失败:", err);
  process.exit(1);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:42:22