Node.js调用Weather API浏览器数据不更新 命令行可正常获取实时数据
问题描述
Node开发初学者调用天气API开发天气查询功能时遇到异常:浏览器端访问服务时,API返回的天气数据始终无法更新为最新值,但通过命令行发起请求时可以正常获取实时天气预报结果。
原实现代码
const express = require("express"); const { all } = require("express/lib/application"); // HTTPS library requrired` const https = require("https"); const app = express(); const port = 3000; app.get("/", function(req, res){ // Getting data from external server const url = "https://api.openweathermap.org/data/2.5/weather?q=Mumbai&appid=---------------------------------&units=metric"; // Adding functions to our own server https.get(url, function(respone){ console.log(respone.statusCode); // Getting data and putting on our server respone.on("data", function(data){ // Parsing the data to an actuall javascript object var allData = JSON.parse(data) const temp = allData.main.temp; const description = allData.weather[0].description; const icon = allData.weather[0].icon; const imageUrl = "http://openweathermap.org/img/wn/"+ icon +"@2x.png" res.write("<p>The weather type here is: "+description+"</p>") res.write("<h1>The temperature here is: "+temp+"</h1>") res.write("<img src = "+imageUrl+"></img>"); res.send(); console.log(allData) }) }) }) app.listen(port, function(){ console.log("Server is running on port 3000"); })
问题原因
- 核心诱因是浏览器默认缓存策略:浏览器对GET类型的静态响应默认会做本地缓存,你的接口没有返回任何禁用缓存的响应头,多次访问时浏览器会直接读取本地存储的旧页面,不会重新向Node服务发起请求,自然拿不到最新数据;而命令行请求默认不使用缓存,每次都会完整发起请求,因此可以拿到实时结果。
- 代码存在隐性逻辑缺陷:Node.js中
https.get返回的响应是流对象,data事件会在接收到数据块时多次触发,你直接在data事件回调里解析JSON、返回响应,当接口返回数据量较大需要分块传输时,会出现JSON解析失败、数据截断的问题,当前只是因为天气接口返回数据量小才暂时没有触发报错。 - 代码存在语法不规范问题:请求URL里的参数分隔符
&被错误写成了HTML转义字符&,不符合URL规范,容易触发接口参数解析错误;回调参数名respone属于拼写错误(正确拼写为response),同时存在未使用的冗余导入。
修复方案
- 在接口响应中添加禁用缓存的响应头,强制浏览器每次访问都重新发起请求
- 调整流处理逻辑,先收集所有数据块,在响应的
end事件触发后再拼接、解析完整数据,之后再返回结果 - 修正URL中的转义错误,把
&替换为正确的& - 修正拼写错误,移除未使用的冗余导入
修复后完整代码
const express = require("express"); const https = require("https"); const app = express(); const port = 3000; app.get("/", function(req, res){ // 设置禁用缓存的响应头,兼容HTTP1.0/1.1 res.set({ "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0" }); // 修正URL中的转义错误,替换&为& const url = "https://api.openweathermap.org/data/2.5/weather?q=Mumbai&appid=---------------------------------&units=metric"; https.get(url, function(response){ console.log(response.statusCode); // 存储所有接收到的数据块 let chunks = []; response.on("data", function(chunk){ chunks.push(chunk); }); // 数据全部接收完成后统一处理 response.on("end", function(){ const allData = JSON.parse(Buffer.concat(chunks).toString()); const temp = allData.main.temp; const description = allData.weather[0].description; const icon = allData.weather[0].icon; const imageUrl = "http://openweathermap.org/img/wn/"+ icon +"@2x.png"; res.write("<p>The weather type here is: "+description+"</p>"); res.write("<h1>The temperature here is: "+temp+"</h1>"); res.write("<img src = "+imageUrl+"></img>"); res.send(); console.log(allData); }) }) }) app.listen(port, function(){ console.log("Server is running on port 3000"); })
替换代码后重启Node服务,在浏览器端按Ctrl+F5强制刷新清掉旧缓存后再访问,即可正常获取实时更新的天气数据。
内容的提问来源于stack exchange,提问作者Ayush Parui
相关产品推荐
相关产品推荐

