React+Node架构项目如何调用spawn运行Python图书推荐脚本
第一步:修正后端server.js代码
你当前的后端写法存在3个问题:
- spawn逻辑写在路由外,仅服务启动时执行1次,无法根据用户访问的商品ID动态生成推荐结果
- 未将Python脚本返回的推荐数据响应给前端
- 全局复用同一个pythonProcess实例,多用户请求时会出现数据串扰
修正后的代码如下:
const spawn = require("child_process").spawn; const express = require('express'); const app = express(); // 允许前端跨域请求,开发环境可以加这个,生产环境按需配置 // 需要先执行 npm install cors 安装依赖 const cors = require('cors'); app.use(cors()); app.get("/api/recommend/:bookName", (req, res) => { // 每次请求都新启动Python进程,动态传入当前访问的图书名/ID // 你可以根据需求把req.params.bookName换成从商品接口取到的对应图书名称 const pythonProcess = spawn('python', ["../python/book_recommendation.py", req.params.bookName]); let result = ''; // 拼接Python脚本返回的流式数据 pythonProcess.stdout.on('data', (data) => { result += data.toString(); }); // 进程执行结束后把结果返回给前端 pythonProcess.on('close', (code) => { if (code === 0) { // 建议你Python脚本直接输出JSON格式,前端可以直接解析 res.json({ recommendations: JSON.parse(result) }); } else { res.status(500).json({ error: '推荐服务调用失败' }); } }); // 捕获进程执行错误 pythonProcess.stderr.on('error', (err) => { res.status(500).json({ error: err.message }); }); }); // 原有商品接口保留 app.get("/product/:id", (req, res) => { // 原有返回商品详情的逻辑不变 });
第二步:前端ProductScreen调用接口
你可以在页面组件挂载时,用fetch或者axios请求后端的推荐接口,示例代码如下(用原生fetch演示):
import { useEffect, useState } from 'react'; const ProductScreen = () => { const [recommendations, setRecommendations] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { // 这里的bookName替换成你当前商品对应的图书名称,也可以传商品ID后端自行映射 const currentBookName = "Timeline"; // 前后端同域部署时可以直接写相对路径 /api/recommend/xxx,无需完整域名 fetch(`http://你的后端地址/api/recommend/${encodeURIComponent(currentBookName)}`) .then(res => res.json()) .then(data => { setRecommendations(data.recommendations); setLoading(false); }) .catch(err => { console.error('获取推荐失败', err); setLoading(false); }); }, []); // 依赖项可以换成当前商品ID,切换商品时重新请求 // 后续页面渲染时就可以用recommendations数组渲染推荐列表了 return ( <div> {/* 原有商品详情渲染逻辑 */} <div className="recommendation-section"> <h3>为你推荐</h3> {loading ? <p>加载推荐中...</p> : ( <ul> {recommendations.map((book, idx) => ( <li key={idx}>{book.name}</li> ))} </ul> )} </div> </div> ) } export default ProductScreen;
内容的提问来源于stack exchange,提问作者Yash Vishe
相关产品推荐
相关产品推荐

