【问题标题】:Requesting infromation from a API through Node.js通过 Node.js 从 API 请求信息
【发布时间】:2020-07-09 09:23:42
【问题描述】:

希望您能帮帮我,我正在运行 Node.js 并尝试从 API 获取城市名称,但一直显示错误 说它无法读取未定义的属性city_name

卡在代码的这一行:

const cityName = weatherData.data.city_name;

任何线索为什么这样做?请

// Creating the server of the weather app
const express = require('express');
const app = express();


const { StringDecoder } = require('string_decoder');
const decoder = new StringDecoder('utf8');

const https = require('https');


app.get('/', (req, res) => {
    const weatherPath = "https://api.weatherbit.io/v2.0/current?key=41c0f84d717a4764a26d144aa33a9443&city=melbourne,Australia"

    // Calling the weather app 
    https.get(weatherPath, (response) => {
        console.log(response.statusCode);
        
        // Getting the data from the weather app
        response.on('data', (d) => {
            //console.log(d);
            
            
            // Converting the buffer data from the weather app
            console.log(decoder.write(d));

            const weatherData = decoder.write(d);

            const cityName = weatherData.data.city_name;

            console.log(cityName);


          });
    });

    res.send("The server is up and running on the web");

});



app.listen(3000, () => 
{

    console.log('Server is running on port 3000');
});

【问题讨论】:

    标签: node.js arrays json api get


    【解决方案1】:

    您的数据是一个字符串,因此没有这些属性。你需要先JSON.parse它。

    但是还有另一个问题,一旦返回更多数据,您的代码就会中断,因为您只侦听单个数据块。您必须将所有块相加(添加到每个 data 事件的现有块中)并处理 end 事件的完整数据。

    但总的来说https.get 方法非常简单,使用像node-fetch 这样的包会简单得多:

    // Creating the server of the weather app
    const express = require('express');
    const app = express();
    
    const fetch = require('node-fetch')
    
    app.get('/', (req, res) => {
        const weatherPath = "https://api.weatherbit.io/v2.0/current?key=41c0f84d717a4764a26d144aa33a9443&city=melbourne,Australia"
    
        // Calling the weather app 
        fetch(weatherPath)
          .then(response => response.json())
          .then(weatherData => {
            // Getting the data from the weather app 
            const cityName = weatherData.data[0].city_name;
            console.log(cityName); 
          }).catch(e => {
            console.error('An error occured!', e);
          });
    
        res.send("The server is up and running on the web");
    });
    
    app.listen(3000, () => {
        console.log('Server is running on port 3000');
    });
    

    附加信息

    解决您的评论:

    虽然在命令行中它看起来像 JSON,但我将数据转换为字符串。

    “JSON”一词经常以令人困惑的方式使用。从技术上讲,JSON(JavaScript 对象表示法)是一种序列化格式,是对象或其他基本 JavaScript 数据类型的字符串表示(有限制)。 “活动”对象的概念仅存在于脚本内的内存中。因此,API 总是向您发送一串字符。这个字符串“是”JSON,即使用 JSON 作为表示结构化数据的方法,当解析 (!) 时,可以将其转换回 JavaScript 对象(在内存中)。所以你是对的,它看起来像 JSON,但它仍然是一个字符串。

    这就像向您发送房屋的蓝图(2D 表示 - JSON 字符串)(3D 对象 - 原始对象)。 (您显然不能在信中发送房子,所以人们会发送蓝图(JSON)。)它看起来像一所房子,因为它代表一个房子,但您还不能打开它的门(访问房产)或某物。那时,它仍然只是印在一张纸(字符串)上的东西,人们将其识别为蓝图(它是有效的 JSON)。您必须首先根据蓝图建造一个实际的房子(将 JSON 解析回一个对象)。

    (当然,通过使用像 json 这样的变量名来表示从 JSON 解析的数据,当然这并没有变得更好。)

    【讨论】:

    • 太棒了!感谢那。现在有道理了。我将数据转换为字符串,尽管在命令行中它看起来像 JSON。只需要正确转换。感谢有关节点获取的提示,需要进一步研究。 :D
    【解决方案2】:

    我尝试点击 API 和响应:

    {"data":[{"rh":73,"pod":"n","lon":144.96332,"pres":1025.6,"timezone":"Australia\/Melbourne","ob_time":"2020-07-09 09:05","country_code":"AU","clouds":50,"ts":1594285500,"solar_rad":0,"state_code":"07","city_name":"Melbourne","wind_spd":1,"wind_cdir_full":"north-northwest","wind_cdir":"NNW","slp":1026.3,"vis":5,"h_angle":-90,"sunset":"07:16","dni":0,"dewpt":8.2,"snow":0,"uv":0,"precip":0,"wind_dir":348,"sunrise":"21:34","ghi":0,"dhi":0,"aqi":61,"lat":-37.814,"weather":{"icon":"c02n","code":"802","description":"Scattered clouds"},"datetime":"2020-07-09:09","temp":12.8,"station":"E5657","elev_angle":-20.02,"app_temp":12.8}],"count":1}
    

    编辑:
    我之前没有在应用程序中尝试您的代码,我通过浏览器尝试
    这是我的代码

    // Calling the weather app 
        https.get(weatherPath, (response) => {  
            response.setEncoding('utf8')
            let chunks = []
            // Getting the data from the weather app
            response.on('data', (d) => {
                chunks.push(d);
            });
            response.on('end', () => {
               let data = JSON.parse(chunks.join(''))
               console.log(data.data[0].city_name)
            });
    
              
        });
    

    weather.data 是一个数组,因此当您尝试访问时,weather.data.city_name 将是未定义的。您必须访问weather.data[0].city_name

    【讨论】:

    • 我试过了,但仍然出现同样的错误。常量 cityName = weatherData.data[0].city_name; ^ 类型错误:无法读取未定义的属性“0”
    • 对不起,我从浏览器中尝试了您的数据,而不是从应用程序代码中尝试,我将在应用程序代码中尝试
    【解决方案3】:

    我已经使用通常称为axios的高级节点模块解决了

    看看代码,

    // Creating the server of the weather app
    const express = require('express');
    const app = express();
    const axios = require('axios');
    
    app.get('/', (req, res) =>
    {
        //In production we do not need this
        process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
        const weatherPath = "https://api.weatherbit.io/v2.0/current?key=41c0f84d717a4764a26d144aa33a9443&city=melbourne,Australia";
        axios.get(weatherPath)
            .then(function (response)
            {
                // handle success
                let cityName = response.data.data[0].city_name;
                console.log(cityName);
            })
            .catch(function (error)
            {
                // handle error
                console.log(error);
            })
            .finally(function ()
            {
                // always executed
            });
        res.send("The server is up and running on the web");
    });
    
    
    app.listen(3000, () =>
    {
    
        console.log('Server is running on port 3000');
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-31
      • 2021-06-05
      • 2023-03-11
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      相关资源
      最近更新 更多