Api数据与Node.jsasynchronous并检索数据使其同步

我需要帮助,我正在做一个节点的天气应用程序。 我使用Google API来获取地址的经纬度,并将其反馈到Dark Sky API中,以便以JSON格式返回天气。

我的问题是,大多数时候天气API在google API返回经度和纬度之前进行search。 我知道为什么要这样做,因为Node的asynchronous性质。 我的问题是如何使这部分同步呢?

var express = require('express'); var https = require('https') var bodyParser = require("body-parser"); var app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); var lon; var lat; app.post('/', function(req,res,next){ var search = req.body.search; function google(){ var api = "API-KEY"; var url = https.get(`https://maps.googleapis.com/maps/api/geocode/json?address=${search}&key=${api}`, function(res3){ var body = ""; var googleResults; res3.on('data', function(data){ body += data.toString(); }) res3.on('end', function(){ googleResults = JSON.parse(body); //console.log(body); lat = googleResults.results[0].geometry.location.lat; lon = googleResults.results[0].geometry.location.lon; console.log(search); }) }); } google(); //connectc to API URL() var request = https.get(`https://api.darksky.net/forecast/API-KEY/${lon},${lat}`, function(res2){ console.log(lon + " " + lat) var body = ""; var weather; //Read the data res2.on('data', function(data){ body += data.toString(); }) res2.on('end', function(){ //Parse the data weather = JSON.parse(body); //Print data //console.log("test = " + weather.currently.temperature) res.render('index', { temperature: weather.currently.temperature, humidity: weather.currently.humidity, wind: weather.currently.windSpeed }); }) }); }); 

最简单的事情就是让google()把一个callback函数作为一个参数。 然后你可以使用这个callback函数来触发黑暗的天空。

 var express = require('express'); var https = require('https') var bodyParser = require("body-parser"); var app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.post('/', function(req, res, next) { var search = req.body.search; // Have google() take a callback function as an argument and // call that function with the data when it's done. function google(cb) { var api = "API-KEY"; var url = https.get(`https://maps.googleapis.com/maps/api/geocode/json?address=${search}&key=${api}`, function(res3) { var body = ""; var googleResults; res3.on('data', function(data) { body += data.toString(); }) res3.on('end', function() { googleResults = JSON.parse(body); //console.log(body); lat = googleResults.results[0].geometry.location.lat; lon = googleResults.results[0].geometry.location.lon; // Call the function here cb(lat, lon); }) }); } // Now use the callback to do your second request to darksky google(function(lat, lon) { //connectc to API URL() var request = https.get(`https://api.darksky.net/forecast/API-KEY/${lon},${lat}`, function(res2) { console.log(lon + " " + lat) var body = ""; var weather; //Read the data res2.on('data', function(data) { body += data.toString(); }) res2.on('end', function() { //Parse the data weather = JSON.parse(body); //Print data //console.log("test = " + weather.currently.temperature) res.render('index', { temperature: weather.currently.temperature, humidity: weather.currently.humidity, wind: weather.currently.windSpeed }); }) }); }}); }); 

这不是解决问题的最简单或最容易的方式,但是我一直在使用await关键字和node-fetch库来完成这些请求。

基本上, node-fetch工作在Promises上,这意味着你可以使用它来发出请求,并且在请求完成之后使用.then()做一些事情。 await关键字将所有嵌套的代码转换为同步代码,这意味着更容易阅读和保存。 以下是您的代码如何使用它们的样子:

 var express = require('express'); var https = require('https') var bodyParser = require("body-parser"); var app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); var lon; var lat; app.post('/', (req, res, next) => { var search = req.body.search; async function google() { var api = ""; var googleResults = await (await fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=${search}&key=${api}`)).json() lat = googleResults.results[0].geometry.location.lat; lon = googleResults.results[0].geometry.location.lon; console.log(search) } }); (async() => await google())(); //connectc to API URL() var weather = await (await fetch(`https://api.darksky.net/forecast/7c41453dc9e5976eecb6a38487427b58/${lon},${lat}`)).json(); console.log(lon + " " + lat) res.render('index', { temperature: weather.currently.temperature, humidity: weather.currently.humidity, wind: weather.currently.windSpeed }); 

值得注意的是,由于await是ES6的一部分,因此您可能需要使用诸如babel之类的东西在较旧的浏览器上运行它。

在这里使用NodeJS的asynchronous特性(使用节点式callback,承诺等)

例如,只需在你的google函数中添加一个callback参数,并且在callback被触发之前不要运行你的http请求。 例如,你的谷歌function可能成为以下,然后你打电话谷歌,并在callback中运行以下代码:

 function google(callback){ callback = callback || function() {} var api = "API-KEY"; var url = https.get(`https://maps.googleapis.com/maps/api/geocode/json?address=${search}&key=${api}`, function(res3){ var body = ""; var googleResults; res3.on('data', function(data){ body += data.toString(); }) res3.on('end', function(){ googleResults = JSON.parse(body); //console.log(body); lat = googleResults.results[0].geometry.location.lat; lon = googleResults.results[0].geometry.location.lon; console.log(search); callback() }) }); } google(function() { //execute your request and subsequent calls and app logic here }) 

注意:我build议传递参数或者在callback中返回latlon ,而不是用latlon来拉伸全局范围,但是这仍然可行。