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

如何在server.js接收Webhook时调用game.js中的webhookEvent函数?

问题:Express接收Webhook时调用前端game.js中的函数

我有一个用Express接收指定URL Webhook的项目,包含index.html和实现简易井字棋的game.js(通过script标签引入)。目前Web应用正常显示,井字棋能运行,接收Webhook时console.log(req.body);也能正常执行。

需求:希望server.js接收到Webhook时,调用game.js里的webhookEvent()函数,但刚接触JavaScript/Node.js,不知道怎么实现从server.js调用前端game.js的函数,求帮助。


项目结构

project
  │   server.js
  │   package.json  
  │
  └───src
  │   │   index.html
  │   │   game.js

文件内容

server.js(启动脚本)

const express = require("express");
var app = express()
const path = require('path');

app.use(express.static(path.join(__dirname, 'src')));

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'src', 'index.html'));
});

app.use(express.urlencoded({ extended: false }));

app.post("/webhook", (req, res) => {
  console.log(req.body);
  res.sendStatus(200);
});

var listener = app.listen(process.env.PORT, function () {
  console.log("Your bot is running on port " + listener.address().port);
});

package.json(将server.js设为启动脚本)

{
  "name": "project",
   ...
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  ...
}

src/index.html(底部引入game.js)

<!DOCTYPE html>
<html lang="en">
<head>
    ...
</head>
  <body>
    ...
    <script type="module" src="game.js"></script>
  </body>
</html>

src/game.js(需在Webhook触发时执行操作)

if (document.querySelector) {
  document.documentElement.classList.add("js");

  var ticTacToeElement = document.querySelector("#tic-tac-toe");
  ...
}

function webhookEvent() {
  // Webhook接收时执行的操作
}

已尝试的方法

  • 从server.js导出app:module.exports = app; → 问题:game.js中用var app = require("../server.js");引入后,脚本无法正常运行。
  • 从game.js导出webhookEvent:export {webhookEvent}; 并在server.js中引入 → 行不通,因为server.js先启动,无法从前端的game.js导入函数。

解决方案

核心问题是:Node.js后端(server.js)和前端浏览器环境(game.js)是完全独立的运行环境,后端无法直接调用前端函数,必须通过「前端主动监听+后端推送/告知」的方式实现。以下是两种可行方案:

方案1:WebSocket(实时双向通信,适合高实时性场景)

WebSocket可让后端与前端建立持久连接,后端收到Webhook时直接推送消息触发前端函数。

步骤1:安装WebSocket库

npm install ws

步骤2:修改server.js,添加WebSocket支持

const express = require("express");
const WebSocket = require('ws');
const path = require('path');

var app = express()
app.use(express.static(path.join(__dirname, 'src')));

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'src', 'index.html'));
});

app.use(express.urlencoded({ extended: false }));

// 启动WebSocket服务器
const wss = new WebSocket.Server({ noServer: true });
wss.on('connection', (ws) => {
  console.log('前端已连接');
  ws.on('close', () => {
    console.log('前端连接断开');
  });
});

// 修改Webhook接口,推送消息给所有连接的前端
app.post("/webhook", (req, res) => {
  console.log(req.body);
  // 给所有在线前端发送消息
  wss.clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({ type: 'webhook', data: req.body }));
    }
  });
  res.sendStatus(200);
});

// 让Express服务器与WebSocket共享端口
const listener = app.listen(process.env.PORT, function () {
  console.log("Your bot is running on port " + listener.address().port);
  listener.on('upgrade', (request, socket, head) => {
    wss.handleUpgrade(request, socket, head, (ws) => {
      wss.emit('connection', ws, request);
    });
  });
});

步骤3:修改game.js,监听WebSocket消息

if (document.querySelector) {
  document.documentElement.classList.add("js");

  var ticTacToeElement = document.querySelector("#tic-tac-toe");
  ...
}

// 建立WebSocket连接
const ws = new WebSocket(`ws://${window.location.host}`);
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  if (message.type === 'webhook') {
    webhookEvent();
    // 可通过message.data获取Webhook的具体内容
  }
};

function webhookEvent() {
  // Webhook触发时执行的操作
  console.log('Webhook已触发,执行对应操作');
}

方案2:前端轮询(简单易实现,适合低实时性场景)

前端定期向后端请求,检查是否有新的Webhook事件,存在则触发对应函数。

步骤1:修改server.js,保存最近的Webhook事件

const express = require("express");
const path = require('path');

var app = express()
app.use(express.static(path.join(__dirname, 'src')));

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'src', 'index.html'));
});

app.use(express.urlencoded({ extended: false }));

// 存储最近的Webhook事件,初始为null
let latestWebhook = null;

app.post("/webhook", (req, res) => {
  console.log(req.body);
  latestWebhook = { data: req.body, timestamp: Date.now() };
  res.sendStatus(200);
});

// 添加接口供前端查询Webhook状态
app.get("/check-webhook", (req, res) => {
  res.json(latestWebhook);
  // 返回后重置状态,避免重复触发
  latestWebhook = null;
});

var listener = app.listen(process.env.PORT, function () {
  console.log("Your bot is running on port " + listener.address().port);
});

步骤2:修改game.js,添加轮询逻辑

if (document.querySelector) {
  document.documentElement.classList.add("js");

  var ticTacToeElement = document.querySelector("#tic-tac-toe");
  ...
}

// 每3秒检查一次是否有新的Webhook事件
setInterval(async () => {
  const response = await fetch('/check-webhook');
  const event = await response.json();
  if (event) {
    webhookEvent();
    // 可通过event.data获取Webhook具体内容
  }
}, 3000);

function webhookEvent() {
  // Webhook触发时执行的操作
  console.log('Webhook已触发,执行对应操作');
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:15:35