Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript API调用上的Node.js循环_Javascript_Node.js_Api_Csv_Object - Fatal编程技术网

Javascript API调用上的Node.js循环

Javascript API调用上的Node.js循环,javascript,node.js,api,csv,object,Javascript,Node.js,Api,Csv,Object,我正在尝试使用不同的参数来获取一些API调用。获取数据并按天、城市最高温度、城市最低温度和有雨城市将其转换为CSV文件 API示例: 我有以下带有cities和api密钥的对象: const cities = { 0: ['Jerusalem', 'il'], 1: ['New York', 'us'], 2: ['Dubai', 'ae'], 3: ['Lisbon', 'pt'], 4: ['Oslo', 'no'], 5: ['Paris'

我正在尝试使用不同的参数来获取一些API调用。获取数据并按天、城市最高温度、城市最低温度和有雨城市将其转换为CSV文件

API示例:

我有以下带有cities和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']);

});
我曾尝试使用带有key in对象的for循环,但不幸的是,它没有显示数据,错误原因未定义。

您可以使用它来实现这一点

当所有 作为可替代品通过的承诺已解决或当可替代品 没有承诺

您可以使用来实现这一点

当所有 作为可替代品通过的承诺已解决或当可替代品 没有承诺


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

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

请务必指出,我是按本地日期分组的,如果您希望按utc日期分组,则应更改行:

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

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

我现在已更新到group by date,结果如下所示:

按本地日期分组:

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

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

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

请务必指出,我是按本地日期分组的,如果您希望按utc日期分组,则应更改行:

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

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

我现在已更新到group by date,结果如下所示:

按本地日期分组:

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


您是在响应中获取数据还是在主体中获取数据?在主体中,我解析数据并将其保存到数据中。logs工作得很好,我只想使用从object cities获得的不同参数在API上进行循环。我想我们需要使用Promise,但我对它不太熟悉,这给我带来了很多麻烦。您是在响应中获取数据还是在body中获取数据?在body中,我解析它并将其保存到数据中。logs工作得很好,我只想使用从object cities获得的不同参数在API上进行循环。我想我们需要使用Promise,但我对它不太熟悉,这给我带来了很多麻烦。如果我在Promise中调用API,那么在get data中获取(URL)的目的是什么?好吗?@YonatanDarmon我忽略了这一点,谢谢。在
getData
中编辑了多余的promise调用。您正在
城市
fetch
中循环,逐个提取数据,然后
promise。all
将所有数据作为单个promise返回。但是fetch URL不是动态的,只能得到一个响应。我需要动态地这样做,如果我在阵列中更改城市,它将能够继续进行新的更改。我在问题的顶部添加了一个API示例,如果我在Promise中调用API,那么在get data中获取(URL)的目的是什么。好吗?@YonatanDarmon我忽略了这一点,谢谢。在
getData
中编辑了多余的promise调用。您正在
城市
fetch
中循环,逐个提取数据,然后
promise。all
将所有数据作为单个promise返回。但是fetch URL不是动态的,只能得到一个响应。我需要动态地这样做,如果我在阵列中更改城市,它将能够继续进行新的更改。我在我的问题上添加了一个API示例。这个答案为我提供了迄今为止最好的解决方案,顺便说一句,我添加了一些函数来获取每个城市的最高和最低温度,我将添加一些功能,以最高温度、最低温度对城市进行排序。等每个响应将为我们提供40个数据点,每天最多8个。这通常意味着我们将获得6天的数据(2部分+4完成),例如5,8,8,8,3。我认为为一天分配天气最可靠的方法是使用dt unix时间戳,并使用矩.js,或许可以从中获取一天(矩.utc(dt))(我猜他们使用的是utc时间!)如果我们只跳过每8个数据点,我们就有可能为天气分配错误的一天。啊,是的,我知道你在做什么,您将在5天内间隔1天拍摄快照。那就行了!我的逻辑是从每个位置的40个读数中获得最大值(每个参数)。我明白你的意思,这是一个很好的逻辑,但我尝试了更简单的方法。如果您在发布的答案上更改了,请告诉我,同时我将尝试计算如何显示五个不同的日期,并在每一天之间进行比较。这样我就可以将最终结果显示到CSV文件中。这个答案给了我迄今为止最好的解决方案,我如何操作它顺便说一句。我添加了一些函数来获取每个城市的最高和最低温度,我将添加一些功能,以按最高温度、最低温度对城市进行排序。等每个响应将为我们提供40个数据点,每天最多8个。这通常意味着我们将获得6天的数据(2部分+4补偿