如何在Node.js/Express中存储POST请求数据并在另一函数处理
问题解决思路及代码修正
核心问题梳理
- 请求方式不匹配:后端提供的是
POST /movies接口,但前端loadMovies函数发送的是GET请求,既无法触发后端POST逻辑,也无法传递选中的复选框数据(imdbIDs数组)。 - 异步请求处理漏洞:后端用
forEach循环发起异步http.get请求,通过index === imdbIDs.length - 1判断是否所有请求完成不可靠——异步请求的完成顺序不一定和循环顺序一致,可能导致还没收集完所有电影数据就提前返回响应。 - 前端响应数据获取错误:前端尝试用
xhr.responseData获取响应数据是错误的,XMLHttpRequest的响应数据应该用xhr.responseText(字符串格式)或xhr.response(解析后的对象,需设置响应类型)。
前端代码修正(index.js)
修改loadMovies函数,改为发送POST请求,传入选中的imdbIDs数组,并正确处理响应:
function loadMovies(selectedImdbIDs) { // 接收选中的imdbIDs数组作为参数 const xhr = new XMLHttpRequest(); xhr.onload = function () { const mainElement = document.querySelector("main"); // 清空main内容 while (mainElement.childElementCount > 0) { mainElement.firstChild.remove(); } if (xhr.status === 200) { try { const movies = JSON.parse(xhr.responseText); // 正确解析响应文本 movies.forEach(movie => new MovieBuilder(movie, deleteMovie).appendTo(mainElement)); } catch (parseError) { mainElement.append(`解析数据失败: ${parseError.message}`); } } else { mainElement.append(`数据加载失败,状态码 ${xhr.status} - ${xhr.statusText}`); } }; // 设置请求头,告诉后端发送的是JSON数据 xhr.open("POST", "/movies"); xhr.setRequestHeader("Content-Type", "application/json"); // 发送选中的imdbIDs数组(转为JSON字符串) xhr.send(JSON.stringify(selectedImdbIDs)); } // 调用示例:从复选框中获取选中的imdbIDs // const selectedImdbIDs = Array.from(document.querySelectorAll('input[type="checkbox"]:checked')) // .map(checkbox => checkbox.value); // loadMovies(selectedImdbIDs);
后端代码修正(server.js)
用Promise封装每个http.get请求,通过Promise.all等待所有请求完成后再返回响应,避免异步顺序问题:
// 建议用https(OMDB支持https),保持请求协议一致性 const https = require('https'); // 必须先配置JSON解析中间件,放在POST接口之前 app.use(express.json()); app.post("/movies", async function (req, res) { const imdbIDs = req.body; if (!Array.isArray(imdbIDs)) { return res.sendStatus(400); } const apiKEY = '########'; // 封装http.get为Promise,方便异步控制 const fetchMovie = (imdbID) => { return new Promise((resolve, reject) => { const apiUrl = `https://www.omdbapi.com/?apikey=${apiKEY}&i=${imdbID}`; https.get(apiUrl, (response) => { let responseData = ''; response.on('data', (chunk) => { responseData += chunk; }); response.on('end', () => { try { const movieData = JSON.parse(responseData); if (movieData.Response === 'True') { const movie = { Released: new Date(movieData.Released).toISOString(), Runtime: movieData.Runtime !== 'N/A' ? parseInt(movieData.Runtime) : null, Genres: movieData.Genre.split(',').map(genre => genre.trim()), Directors: movieData.Director.split(',').map(director => director.trim()), Writers: movieData.Writer.split(',').map(writer => writer.trim()), Actors: movieData.Actors.split(',').map(actor => actor.trim()), MetaScore: movieData.Metascore !== 'N/A' ? parseInt(movieData.Metascore) : null, imdbRating: Number(movieData.imdbRating) }; resolve(movie); } else { console.error(`获取电影失败 imdbID: ${imdbID},错误: ${movieData.Error}`); resolve(null); // 失败时返回null,后续过滤掉无效项 } } catch (error) { console.error('解析电影数据失败:', error); resolve(null); } }); }).on('error', (error) => { console.error('请求OMDB接口失败:', error); resolve(null); }); }); }; // 并发请求所有电影数据,等待全部完成 const moviePromises = imdbIDs.map(id => fetchMovie(id)); const results = await Promise.all(moviePromises); // 过滤掉请求失败的null项 const movies = results.filter(movie => movie !== null); res.status(200).send(movies); });
额外注意事项
- 后端必须配置
express.json()中间件,才能正确解析前端发送的JSON格式请求体。 - OMDB API支持HTTPS协议,建议后端使用
https.get发起请求,避免浏览器安全警告和潜在的请求失败问题。
内容的提问来源于stack exchange,提问作者Un1cat
相关产品推荐
相关产品推荐

