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

Puppeteer使用setInterval时报会话关闭错误 如何实现页面持久驻留?

问题解答

错误原因

你的代码逻辑执行顺序存在问题:

  • setInterval属于异步非阻塞API,注册完成后主线程不会等待其回调执行,会直接继续向下运行
  • try块代码执行完毕后,会直接执行你写在try语句外的await page.close()和await browser.close(),直接销毁页面和浏览器实例
  • 等setInterval的回调首次触发时,操作的已经是被销毁的实例,自然会抛出会话关闭的错误,和你设置的间隔时长没有任何关系。

修复方案

1. 移除错误位置的关闭逻辑

你需要永久保持页面运行,所以不要主动调用page.close()和browser.close(),直接删除这两行代码即可。

2. 替换setInterval为递归setTimeout

setInterval不会等待上一次回调内的异步任务执行完成就会触发下一次,容易出现并发操作冲突,使用递归的setTimeout可以保证上一轮任务完全执行完毕后,再等待指定间隔触发下一轮任务,更稳妥。

修复后完整代码

const puppeteer = require('puppeteer');
const creds = require("./creds.json");

(async () => {
    try {
        const browser = await puppeteer.launch({
            // 可选配置,避免长时间运行出现兼容性问题
            defaultViewport: null,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });
        const page = await browser.newPage();
        await page.goto('https://www.online-messenger.com');

        await goToChats(page);
        await page.waitForSelector('div[aria-label="Chats"]');

        // 定义轮询任务
        const pollTask = async () => {
            try {
                let index = 1;
                while (index <= 5) {
                    if (await isUnread(page, index)) {
                        await page.click(`#local-chat`);
                        await page.waitForSelector('div[role="main"]', { timeout: 15000 });

                        let conversationName = await getConversationName(page);
                        if (isChat(conversationName)) {
                            await writeMessage(page);
                        }
                    }
                    index++;
                }
            } catch (taskErr) {
                // 单轮任务异常不中断后续轮询,仅打印错误
                console.error('单轮任务执行异常:', taskErr);
            } finally {
                // 本轮任务执行完成后,30秒后启动下一轮
                setTimeout(pollTask, 30000);
            }
        }

        // 启动第一轮任务
        await pollTask();

        // 阻塞主进程,避免程序退出
        await new Promise(() => {});
    } catch (e) {
        console.error('主流程运行异常:', e);
        // 主流程异常时可根据需求添加重启逻辑
    }
})();

额外优化建议

  • 可以在首次登录完成后调用await page.cookies()将登录态导出存储到本地文件,下次启动浏览器时直接注入cookie,就算浏览器意外崩溃也不需要重复登录
  • 给所有waitForSelector添加超时时间配置,避免单步操作卡住整轮任务
  • 可以监听page.error和browser.disconnected事件,触发时自动重启浏览器实例,提升长时间运行的稳定性
  • 如果担心页面长时间运行卡顿,可以每间隔几小时调用一次page.reload()刷新页面,只要登录态有效就不需要重新登录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 21:18:02