为了账号安全,请及时绑定邮箱和手机立即绑定

API 调用上的 Node.js 循环

API 调用上的 Node.js 循环

哈士奇WWW 2021-12-12 17:51:04
我正在尝试使用不同的参数进行少量 API 调用。获取数据并按天、城市最高温度、城市最低温度和有雨城市将其转换为 CSV 文件。API 示例:https : //samples.openweathermap.org/data/2.5/forecast?q=M%C3%BCnchen,DE&appid=b6907d289e10d714a6e88b30761fae22我有以下带有城市和 api 密钥的对象:const cities = {    0: ['Jerusalem', 'il'],    1: ['New York', 'us'],    2: ['Dubai', 'ae'],    3: ['Lisbon', 'pt'],    4: ['Oslo', 'no'],    5: ['Paris', 'fr'],    6: ['Berlin', 'de'],    7: ['Athens', 'gr'],    8: ['Seoul', 'kr'],    9: ['Singapore', 'sgp'],}const apiKey = "[retracted]";这是我想动态迭代的 API 调用,目前我只在第一个对象参数上运行它并最终将信息推送到天气,以便我可以操纵数据按天(前 5 天)对其进行排序,然后显示城市气温最高、气温最低的城市和所有下雨的城市:request(`http://api.openweathermap.org/data/2.5/forecast?q=${cities[1][0]},${cities[1][1]}&mode=json&appid=${apiKey}`, (error, response, body) => {    let data = JSON.parse(body);        let weather = {        0: [day, highTemp, lowTemp, rain],        1: [day, highTemp, lowTemp, rain],        2: [day, highTemp, lowTemp, rain],        3: [day, highTemp, lowTemp, rain],        4: [day, highTemp, lowTemp, rain],    }    // day 1    console.log(data['city']['name']);    console.log(data['list'][0].dt_txt);    console.log(data['list'][0].main['temp']);    // day 2    console.log(data['city']['name']);    console.log(data['list'][8].dt_txt);    console.log(data['list'][8].main['temp']);    // day 3    console.log(data['city']['name']);    console.log(data['list'][16].dt_txt);    console.log(data['list'][16].main['temp']);    // day 4    console.log(data['city']['name']);    console.log(data['list'][24].dt_txt);    console.log(data['list'][24].main['temp']);    // day 5    console.log(data['city']['name']);    console.log(data['list'][32].dt_txt);    console.log(data['list'][32].main['temp']);});我尝试使用带有对象中的键的 for 循环,但不幸的是它不显示数据,错误原因未定义。
查看完整描述

2 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

我建议使用 response-promise-native 来允许使用 async/await。这将允许我们遍历城市列表并将每个城市的天气数据附加到城市详细信息(名称和国家/地区)。


一旦我们有了这些数据,我们就可以进行您提到的处理,我们可以获得最高和最低温度(请注意,温度以开尔文为单位,因此我们将转换为摄氏度。)


重要的是要指出我按本地日期分组,如果您希望按UTC 日期分组,那么您应该更改该行:


let timeOffset = entry.dt + result.weatherResponse.city.timezone;


let timeOffset = entry.dt;

这是解释数据的一种稍微不同的方式!


我现在已更新为按日期分组,结果如下所示:


按当地日期分组:


Date,Highest Temperature,Lowest Temperature,Cities With Rain

2019-11-01,Dubai,Oslo,"Paris,Berlin"

2019-11-02,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"

2019-11-03,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens,Singapore"

2019-11-04,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens"

2019-11-05,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"

2019-11-06,Singapore,Oslo,"Paris,Berlin,Singapore"

2019-11-07,Seoul,Seoul,""

按 UTC 日期分组:


Date,Highest Temperature,Lowest Temperature,Cities With Rain

2019-11-01,Dubai,Oslo,"Paris,Berlin"

2019-11-02,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"

2019-11-03,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens,Singapore"

2019-11-04,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens"

2019-11-05,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"

2019-11-06,Singapore,Oslo,"Paris,Berlin,Singapore"

代码:


const rp = require("request-promise-native");


const cities = {

    0: ['Jerusalem', 'il'],

    1: ['New York', 'us'],

    2: ['Dubai', 'ae'],

    3: ['Lisbon', 'pt'],

    4: ['Oslo', 'no'],

    5: ['Paris', 'fr'],

    6: ['Berlin', 'de'],

    7: ['Athens', 'gr'],

    8: ['Seoul', 'kr'],

    9: ['Singapore', 'sgp'],

}



async function getWeatherForCities() {

    let results = [];

    for (let [city, countryCode] of Object.values(cities)) {

        console.log(`Getting weather for city: ${city}, country: ${countryCode}...`);

        let weatherResponse = await rp({ url: `http://api.openweathermap.org/data/2.5/forecast?q=${city},${countryCode}&mode=json&appid=${apiKey}`, json: true});

        results.push ({ city, countryCode, list: weatherResponse.list, weatherResponse });

    }


    let summary = results.map(res => {  

        return { city: res.city, countryCode: res.countryCode,

        maxTemperature: getMaxTemperatureCelsius(res.list),

        minTemperature: getMinTemperatureCelsius(res.list),

        totalRainfall: getTotalRainFall(res.list)

    }});


    console.log("Summary (over forecasting interval): ", summary);

    console.log("Result with the highest temperature: ", [...summary].sort((resA, resB) => resB.maxTemperature - resA.maxTemperature)[0]);

    console.log("Result with the lowest temperature: ", [...summary].sort((resA, resB) => resA.minTemperature - resB.minTemperature)[0]);

    console.log("Cities with rain: ", summary.filter(res => res.totalRainfall).map(res => res.city));


    // Group by date (local) and city

    let resultsGroupedByDateAndCity = {};

    results.forEach(result => {

        result.list.forEach(entry => {

            let timeOffset = entry.dt + result.weatherResponse.city.timezone;

            let date = new Date(timeOffset * 1000);

            date.setHours(0,0,0,0);

            let dateKey = date.toISOString().substring(0,10);

            if (!resultsGroupedByDateAndCity[dateKey]) resultsGroupedByDateAndCity[dateKey] = {};

            if (!resultsGroupedByDateAndCity[dateKey][result.city]) resultsGroupedByDateAndCity[dateKey][result.city] = [];

            resultsGroupedByDateAndCity[dateKey][result.city].push(entry);

        });

    });


    // Run through the keys.

    let csvLines = ["Date,Highest Temperature,Lowest Temperature,Cities With Rain"];


    for (let [date, obj] of Object.entries(resultsGroupedByDateAndCity)) {

        let dailySummary = Object.entries(obj).map(([city, dayList]) => {  

            return { city,

            maxTemperature: getMaxTemperatureCelsius(dayList),

            minTemperature: getMinTemperatureCelsius(dayList),

            totalRainfall: getTotalRainFall(dayList)

        }});


        console.log("Details for date " + date + ": ");

        let resultWithHighestTemperature = [...dailySummary].sort((resA, resB) => resB.maxTemperature - resA.maxTemperature)[0];

        let resultWithLowestTemperature = [...dailySummary].sort((resA, resB) => resA.minTemperature - resB.minTemperature)[0];

        let citiesWithRain = dailySummary.filter(res => res.totalRainfall).map(res => res.city);

        console.log("Result with the highest temperature: ", resultWithHighestTemperature);

        console.log("Result with the lowest temperature: ", resultWithLowestTemperature);

        console.log("Cities with rain: ", citiesWithRain);


        csvLines.push([date, resultWithHighestTemperature.city, resultWithLowestTemperature.city, '"' + citiesWithRain.join(",") + '"'].join(","));

    }


    console.log("CSV result:\n", csvLines.join("\n"));

}


function KelvinToCelsius(kelvin) {

    return (kelvin - 273.15);

}


// Return the max temperature for the forecast

function getMaxTemperatureCelsius(responseList) {

    // Get a list of the max temperatures for the forecast.

    const maxTemps = responseList.map(entry => Number(entry.main.temp_max));

    return KelvinToCelsius(Math.max(...maxTemps));

}


// Return the min temperature for the forecast

function getMinTemperatureCelsius(responseList) {

    // Get a list of the min temperatures for the forecast.

    const minTemps = responseList.map(entry => Number(entry.main.temp_min));

    return KelvinToCelsius(Math.min(...minTemps));

}


// Return the total rainfall for the forecast

function getTotalRainFall(responseList) {

    // Get a list of the min temperatures for the forecast.

    const rain = responseList.map(entry => { return entry.rain ? Number(entry.rain["3h"]): 0 });

    return rain.reduce((sum, val) => sum + val, 0)

}


getWeatherForCities();


查看完整回答
反对 回复 2021-12-12
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

您可以使用它Promise.all来实现这一点。


Promise.all 返回一个单一的 Promise,当作为可迭代对象传递的所有承诺都已解决或可迭代对象不包含任何承诺时,该 Promise 会解决。


const getData = (url) => {

   return fetch(url)

    .then(data => data.json())

    .then(jsonData => jsonData)

    .catch(err => {

      console.log("Error while resolving the promise for url", url);        

    });  

}


let arr = [1, 2, 4, 5, 6, 7];


const cities = {

    0: ['Jerusalem', 'il'],

    1: ['New York', 'us'],

    2: ['Dubai', 'ae'],

    3: ['Lisbon', 'pt'],

    4: ['Oslo', 'no'],

    5: ['Paris', 'fr'],

    6: ['Berlin', 'de'],

    7: ['Athens', 'gr'],

    8: ['Seoul', 'kr'],

    9: ['Singapore', 'sgp'],

}


const apiKey = "[retracted]";


Promise.all(Object.keys(cities).map(id => {  

  let url = `http://api.openweathermap.org/data/2.5/forecast?q=${cities[id][0]},${cities[id][1]}&mode=json&appid=${apiKey}`;

  return getData(url);

  }))

 .then(results => {


        // results is an array that contains the result of each api call

        // so you can perform the action that you need here..


        results.map(result => {


          console.log(result['city']['name']);


        });


  })

  .catch(err => {

        // Handle the error..

        console.log(err);

  });  


查看完整回答
反对 回复 2021-12-12
  • 2 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信