嵌套的异步查询

时间:2018-05-16 22:18:31

标签: javascript asynchronous nodes

//express is the framework we're going to use to handle requests
const express = require('express');
//Create a new instance of express
const app = express();
const FormData = require("form-data");
const bodyParser = require("body-parser");
const http = require('http');
const async = require('async');

//This allows parsing of the body of POST requests, that are encoded in JSON
app.use(bodyParser.json());
var router = express.Router();

//AccuWeather API key
const weatherKey = process.env.WEATHER_KEY_TWO;


cityCode = ""; //City code
cityName = "";

//Current Conditions Vars
var ccWeatherText = ""; //Text for weather at location
var ccTemp = 0; //Degrees Farenheit
var ccIcon = 0; //weather icon number https://developer.accuweather.com/weather-icons
var ccURL = "test"; //URL for get
var hourlyData = [];
var fiveDayData = [];

router.post('/', (req, res) => {
    let lat = req.body['lat'];
    let lon = req.body['lon'];
    var latLongCityCodeURL = ("http://dataservice.accuweather.com/locations/v1/cities/geoposition/search?apikey=" + weatherKey + "&q=" + lat + "," + lon);
    //Get city code
    const httpGet = url => {
        return new Promise((resolve, reject) => {
            http.get(url, res => {
                let body = '';
                res.on('data', chunk => body += chunk);
                res.on('end', () => {
                    try {
                        body = JSON.parse(body);
                    } catch (err) {
                        reject(new Error(err));
                    }
                    resolve({
                        code: body.Key,
                        name: body.EnglishName
                    });
                });
            }).on('error', reject);
        });
    };

    //Current Conditions
    const ccGet = url => {
        return new Promise((resolve, reject) => {
            http.get(url, res => {
                let body = '';
                res.on('data', chunk => body += chunk);
                res.on('end', () => {
                    try {
                        body = JSON.parse(body);
                    } catch (err) {
                        reject(new Error(err));
                    }
                    resolve({
                        text: body[0].WeatherText,
                        temp: body[0].Temperature.Imperial.Value,
                        icon: body[0].WeatherIcon
                    });
                });
            }).on('error', reject);
        });
    };

    //12 hour
    const twelveGet = url => {
        return new Promise((resolve, reject) => {
            http.get(url, res => {
                let body = '';
                res.on('data', chunk => body += chunk);
                res.on('end', () => {
                    try {
                        body = JSON.parse(body);
                    } catch (err) {
                        reject(new Error(err));
                    }
                    resolve({
                        body: body
                    });
                });
            }).on('error', reject);
        });
    };

    //5 day
    const fiveGet = url => {
        return new Promise((resolve, reject) => {
            http.get(url, res => {
                let body = '';
                res.on('data', chunk => body += chunk);
                res.on('end', () => {
                    try {
                        body = JSON.parse(body);
                    } catch (err) {
                        reject(new Error(err));
                    }
                    resolve({
                        body: body
                    });
                });
            }).on('error', reject);
        });
    };

    //Get city code from lat lon
    httpGet(latLongCityCodeURL).then(data => {
        cityCode = data.code;
        cityName = data.name;
        ccURL = ("http://dataservice.accuweather.com/currentconditions/v1/" + cityCode + "?apikey=" + weatherKey);
        twelveURL = ("http://dataservice.accuweather.com/forecasts/v1/hourly/12hour/" + cityCode + "?apikey=" + weatherKey);
        fiveURL = ("http://dataservice.accuweather.com/forecasts/v1/daily/5day/" + cityCode + "?apikey=" + weatherKey);
        //Get Current Conditions
        ccGet(ccURL).then(dataCC => {
            ccTemp = dataCC.temp;
            ccWeatherText = dataCC.text;
            ccIcon = dataCC.icon;
            //Get 12 hour forecast
            twelveGet(twelveURL).then(dataTwelve => {
                //Generate hourly data
                for (i = 0; i < dataTwelve.length; i++) {
                    hourlyData[i] = {
                        time: dataTwelve[i].EpochDateTime,
                        temp: dataTwelve[i].Temperature.Value,
                        text: dataTwelve[i].IconPhrase,
                        icon: dataTwelve[i].WeatherIcon
                    };
                }
                console.log("Hourly Data: " + hourlyData);
            }).catch(err => console.log(err));
            fiveGet(fiveURL).then(dataFive => {
                //Generate five day data
                for (i = 0; i < dataFive.length; i++) {
                    fiveDayData[i] = {
                        time: dataFive[i].EpochDate,
                        min: dataFive[i].Temperature.Minimum.Value,
                        max: dataFive[i].Temperature.Maximum.Value,
                        iconDay: dataFive[i].Day.Icon,
                        iconNight: dataFive[i].Night.Icon,
                        dayPhrase: dataFive[i].Day.IconPhrase,
                        nightPhrase: dataFive[i].Night.IconPhrase
                    };
                    console.log("5 Day Data:" + fiveDayData);
                }
                res.send({
                    success: true,
                    cityName: cityName,
                    cityCode: cityCode,
                    currentConditions: {
                        temp: ccTemp,
                        icon: ccIcon,
                        text: ccWeatherText
                    },
                    hourlyData: hourlyData,
                    fiveDayData: fiveDayData
                });
            }).catch(err => console.log(err));
        }).catch(err => console.log(err));
    }).catch(err => console.log('Got error ', err));
});


module.exports = router;

好的,我现在正在NodeJS中创建一个POST方法的端点,它获取纬度和经度的参数。当它获得那些它调用Accuweather的API。我得到了所有精确的工作并返回了正确的结果,但随后我将该代码剪切并粘贴到我的POST方法router.post...中,现在它还没有工作。我知道这是一个ASYNC问题,我只是真的迷失了异步,因为我在router.post里面有3或4个嵌套的异步调用,这是另一个异步调用。所以我认为有一些方法可以将router.post包装到自己的异步调用中,它会在返回结果之前等待天气调用?

我的最终目标:为了让用户发送带有lat和lon的POST,我的代码会执行所有天气调用,并返回POST的数据。

1 个答案:

答案 0 :(得分:0)

您要做的是promise chaining

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) { // (**)

  alert(result); // 1
  return result * 2;

}).then(function(result) { // (***)

  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});

另外,请查看MDN's page on using promises