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

Express.js异步函数完成后通过EJS传文件名报错求助

错误原因分析

ERR_HTTP_HEADERS_SENT错误的核心原因是同一个HTTP请求被发送了两次响应:

  • 当找到匹配的paymentId时,代码执行res.render('app', ...)发送渲染页面的响应;
  • 之后不管订单是否存在,都会执行res.sendStatus(404)再次发送404响应,违反了HTTP协议“一请求一响应”的规则。
修复后的代码
const express = require('express');
const fs = require('fs');
const app = express();
const puppeteer = require('puppeteer');
const path = require('path');

app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, '/public')))

// index page
app.get('/', function(req, res) {
  res.render('index');
});

app.get('/cashpayment/:paymentId', async function(req,res){
  const paymentId = req.params.paymentId;
  const orders = JSON.parse(fs.readFileSync('orders.json'));
  const foundOrder = orders.find(order => String(order.paymentId) === paymentId);
  
  if (foundOrder) {
    // 提取截图逻辑为独立函数,提升可读性
    async function captureScreenshot() {
      const browser = await puppeteer.launch();
      const page = await browser.newPage();
      await page.setViewport({ width: 1280, height: 800 });
      // 建议替换成订单页面的本地路由,比如`http://localhost:1337/order/${paymentId}`
      await page.goto('https://www.nytimes.com/');
      await page.screenshot({ path: './public/nytimes.png', fullPage: true });
      await browser.close();
      console.log('截图完成');
    }

    await captureScreenshot();
    // 静态资源目录是public,所以路径用根目录相对路径即可
    res.render('app', {
      data: '/nytimes.png'
    });
  } else {
    // 仅当未找到订单时返回404
    res.sendStatus(404);
  }
});

app.post('/cashpayment', async function(req,res){
  const paymentId = Math.floor(Math.random() * 1000000000);
  const orders = JSON.parse(fs.readFileSync('orders.json'));
  orders.push({paymentId, paymentAmount: 10, paymentStatus: "UNPAID", token: ""});
  fs.writeFileSync('orders.json', JSON.stringify(orders));
  res.redirect(`/cashpayment/${paymentId}`);
});

app.listen(1337);
console.log('Server is listening on port 1337'); // 原代码端口不一致,这里统一修正
关键修改点说明
  1. 响应逻辑修正:将res.sendStatus(404)移至else分支,确保每个请求仅发送一次响应;
  2. 静态资源路径优化:传递给EJS的图片路径改为/nytimes.png,因为public目录已被设置为静态资源目录,前端可直接通过根路径访问该文件;
  3. 代码结构优化:将截图逻辑提取为独立函数,提升代码可读性;
  4. 端口一致性修正:原代码监听端口1337但日志输出8080,这里统一为1337,避免混淆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:50:36