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

Node/Express天气应用API数据传递问题:GeoNames数据无法传入WeatherBit

天气日志Web应用API数据传递问题

我用Node.js、Express、Cors和Body Parser开发天气日志Web应用,通过Fetch API调用在线接口。已经写完server.js、index.html、app.js,server.js包含Express服务及中间件,app.js实现核心功能。我想先通过GeoNames API获取城市的经纬度,再把经纬度传给WeatherBit API获取对应天气,但现在打印最终数据时返回undefined,没法完成API间的数据传递。

现有代码

Index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Weather Journal</title>
</head>
<body>
    <div id="app">
        <div class="holder headline">Weather Journal App</div>
        <form id="userInfo">
            <div class="holder zip">
                <label for="zip">Enter City here</label>
                <input type="text" id="city" placeholder="enter city here" required>
            </div>
            <div class="holder feel">
                <label for="date">Enter departure date</label>
                <input type="datetime-local" id="date" required>
                <button id="submitBtn" type="submit"> Generate </button>
            </div>
        </form>
        <div class="holder entry">
            <div class="title">Most Recent Entry</div>
            <div id="entryHolder">
                <div id="lat"></div>
                <div id="lng"></div>
                <div id="countryName"></div>
                <div id="temp"></div>
            </div>
        </div>
    </div>
    <script src="app.js" type="text/javascript"></script>
</body>
</html>

app.js

const geoURL = "http://api.geonames.org/searchJSON?";
const geoUsername = `rohanasif1990`;
const weatherURL = "https://api.weatherbit.io/v2.0/forecast/daily?"
const weatherKey = "20028a8267a24bba9a807362767bc4a7"

let d = new Date();
let newDate = d.getMonth() + 1 + "." + d.getDate() + "." + d.getFullYear();

const submitBtn = document.getElementById("submitBtn");

submitBtn.addEventListener("click", (e) => {
    e.preventDefault();
    const city = document.getElementById("city").value;

    if (city !== "") {
        getCity(geoURL, city, geoUsername)
            .then(function (data) {
                getWeather(weatherURL, weatherKey, data["geonames"][0]['lat'], data["geonames"][0]['lng'])
            }).then(weatherData => {
                postWeatherData("/addWeather", { temp: weatherData })
            }).then(function () {
                receiveWeatherData()
            }).catch(function (error) {
                console.log(error);
                alert("Invalid city");
            })
    }
})

const getCity = async (geoURL, city, geoUsername) => {
    const res = await fetch(`${geoURL}q=${city}&username=${geoUsername}`);
    try {
        const cityData = await res.json();
        return cityData;
    }
    catch (error) {
        console.log("error", error);
    }
}

const postWeatherData = async (url = "", data = {}) => {
    const response = await fetch(url, {
        method: "POST",
        credentials: "same-origin",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            temp: data.temp
        })
    });

    try {
        const newData = await response.json();
        return newData;
    }
    catch (error) {
        console.log(error);
    }
}

const receiveWeatherData = async () => {
    const request = await fetch("/allWeather");
    try {
        const allData = await request.json()
        document.getElementById("temp").innerHTML = allData.temp;
    }
    catch (error) {
        console.log("error", error)
    }
}

const getWeather = async (weatherURL, weatherKey, lat, lon) => {
    const res = await fetch(`${weatherURL}&lat=${lat}&lon=${lon}&key=${weatherKey}`);
    try {
        const weatherData = await res.json();
        return weatherData;
    }
    catch (error) {
        console.log("error", error);
    }
}

server.js

// Setup empty JS object to act as endpoint for all routes
cityData = {};
weatherData = {};
picturesData = {};

// Require Express to run server and routes
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

// Start up an instance of app
const app = express();

/* Middleware */
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// Cors for cross origin allowance
app.use(cors())
// Initialize the main project folder
app.use(express.static('website'));

app.get("/all", function sendData(req, res) {
    res.send(cityData);
})

app.get("/allWeather", function sendWeather(req, res) {
    res.send(weatherData);
})

app.get("allPictures", function sendPictures(req, res) {
    res.send(picturesData);
})

app.post("/add", (req, res) => {
    projectData['lat'] = req.body.lat;
    projectData['lng'] = req.body.lng;
    projectData['countryName'] = req.body.countryName
    res.send(cityData);
})

app.post("/addWeather", (req, res) => {
    weatherData['temp'] = req.body.temp;
    res.send(weatherData);
})

app.post("/addPicture", (req, res) => {
    picturesData['pic'] = req.body.pic;
    res.send(picturesData);
})

// Setup Server
app.listen(3000, () => {
    console.log("App listening on port 3000")
    console.log("Go to http://localhost:3000")
})

问题修复点

1. Promise链中断导致数据传递失败

第一个.then中调用getWeather后未返回Promise,导致后续.then拿到undefined。修改如下:

getCity(geoURL, city, geoUsername)
    .then(function (data) {
        // 返回getWeather的Promise,保证链的连续性
        return getWeather(weatherURL, weatherKey, data["geonames"][0]['lat'], data["geonames"][0]['lng'])
    }).then(weatherData => {
        postWeatherData("/addWeather", { temp: weatherData })
    })

2. WeatherBit API请求URL格式错误

weatherURL末尾带有?,拼接参数后会生成非法格式?&lat=...,需要去掉末尾的?:

// 修改前
const weatherURL = "https://api.weatherbit.io/v2.0/forecast/daily?"
// 修改后
const weatherURL = "https://api.weatherbit.io/v2.0/forecast/daily"

3. 未正确提取WeatherBit返回的温度数据

WeatherBit返回的是多日预报对象,需提取具体温度字段(比如当日气温),而非直接传递整个对象:

.then(weatherData => {
    // 取第一天的预报温度,可根据需求调整日期
    const temp = weatherData.data[0].temp;
    postWeatherData("/addWeather", { temp: temp })
})

4. Server路由缺失斜杠

allPictures路由的GET请求缺少开头的/,导致无法访问:

// 修改前
app.get("allPictures", function sendPictures(req, res) {
// 修改后
app.get("/allPictures", function sendPictures(req, res) {

5. Server中未定义的projectData

/add路由使用了未声明的projectData,应替换为已定义的cityData:

app.post("/add", (req, res) => {
    cityData['lat'] = req.body.lat;
    cityData['lng'] = req.body.lng;
    cityData['countryName'] = req.body.countryName
    res.send(cityData);
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:15:38