如何在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
相关产品推荐
相关产品推荐

