簡體   English   中英

API 調用上的 Node.js 循環

[英]Node.js loop on API calls

我試圖用不同的參數進行一些 API 調用。 獲取數據並將其轉換為 CSV 文件,按天、城市最高溫度、城市最低溫度和有雨的城市。

API 示例: https://samples.openweathermap.org/data/2.5/forecast?q=M%C3%BCnchen,DE&appid=b6907d289e10d714a6e88b3076

我有以下 Object 與城市和 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 調用,目前我只在第一個 object 參數上運行它,並最終將信息推送到天氣,這樣我就可以操縱數據以按天排序(前 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']);

});

我嘗試在 object 中使用帶有鍵的 for 循環,但不幸的是它不顯示數據,錯誤原因未定義。

您可以使用Promise.all來實現此目的。

Promise.all 返回一個單獨的 Promise,當所有作為迭代傳遞的承諾都已解決或迭代不包含任何承諾時,該 ZA5A3F0F287A448982 將解決。

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);
  });  

我建議使用 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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM