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

Puppeteer中fetch请求Promise始终处于pending状态问题排查

Puppeteer登录后Fetch请求Promise始终Pending的解决办法

核心问题分析

  1. page.evaluate未传递Fetch的Promise
    原代码里page.evaluate内部执行了fetch,但没有返回这个异步Promise,外部的await只会等evaluate里的同步代码跑完,不会等待fetch请求完成。如果请求因参数错误、服务器无响应等原因卡住,就会一直处于pending状态。

  2. 浏览器上下文变量未正确传入
    this.json_data_在浏览器页面的上下文里是未定义的——page.evaluate的回调运行在浏览器环境,和Node.js上下文完全隔离,直接引用Node端变量会导致请求body为undefined,服务器可能拒绝处理,进而让请求卡住。

  3. 登录导航等待的潜在问题
    即使使用了Promise.all配合waitForNavigation,如果登录是AJAX异步提交而非页面跳转,waitForNavigation会超时,后续的fetch可能在未登录状态下发送,引发异常。


修正后的代码示例

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  try {
    await page.goto('https://id.adform.com/sts/login');

    // 执行登录并等待页面导航完成
    await Promise.all([
      page.evaluate((username, password) => {
        const setValue = Object.getOwnPropertyDescriptor(
          window.HTMLInputElement.prototype,
          "value"
        ).set;
        const modifyInput = (name, value) => {
          const input = document.getElementsByName(name)[0];
          setValue.call(input, value);
          input.dispatchEvent(new Event('input', { bubbles: true }));
          input.dispatchEvent(new Event('change', { bubbles: true })); // 补充change事件触发表单校验
        };
        modifyInput('username', username);
        modifyInput('password', password);
        document.querySelector("button").click();
      }, "another", "some.123"), // 把账号密码作为参数传入,避免上下文冲突
      page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 30000 }), // 添加30秒超时防止无限等待
    ]);

    // 传入请求数据,发送POST并返回结果
    const json_data_ = { /* 你的请求数据 */ };
    const fetchResult = await page.evaluate((jsonData) => {
      return fetch('https://page_after_navigation.com', {
        method: 'POST',
        headers: {
          'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
          'Content-Type': 'application/json', // 告知服务器请求格式
        },
        body: JSON.stringify(jsonData),
      })
      .then(response => {
        if (!response.ok) {
          throw new Error(`请求失败:状态码 ${response.status}`);
        }
        return response.text();
      })
      .catch(error => {
        console.error('Fetch出错:', error);
        throw error; // 抛出错误让外部捕获处理
      });
    }, json_data_); // 将Node端的请求数据传入浏览器上下文

    console.log('请求结果:', fetchResult);
  } catch (error) {
    console.error('流程出错:', error);
  } finally {
    await browser.close();
  }
})();

调试建议

  • 开启可视化调试:启动浏览器时打开开发者工具,直观查看网络请求状态

    const browser = await puppeteer.launch({ headless: false, devtools: true });
    

    在Network面板可以看到fetch请求的发送情况、响应状态、请求头/体是否正确。

  • 验证登录状态:导航完成后,通过截图或页面内容确认是否登录成功

    await page.screenshot({ path: 'after_login.png' });
    const isLoggedIn = await page.evaluate(() => {
      return document.body.textContent.includes('你好,xxx'); // 替换为登录后页面的特征文本
    });
    console.log('是否登录成功:', isLoggedIn);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:35:22