Javascript Api数据与Node.js异步并检索数据使其同步
我需要一个我正在制作的节点天气应用程序的帮助。我使用GoogleAPI获取地址的经度和纬度,并将其输入DarkSkyAPI,以JSON格式返回天气 我的问题是,大多数情况下,天气API在google API返回经度和纬度之前进行搜索。我知道它为什么这样做是因为Node的异步特性。我的问题是如何使此部件同步Javascript Api数据与Node.js异步并检索数据使其同步,javascript,node.js,callback,Javascript,Node.js,Callback,我需要一个我正在制作的节点天气应用程序的帮助。我使用GoogleAPI获取地址的经度和纬度,并将其输入DarkSkyAPI,以JSON格式返回天气 我的问题是,大多数情况下,天气API在google API返回经度和纬度之前进行搜索。我知道它为什么这样做是因为Node的异步特性。我的问题是如何使此部件同步 var express = require('express'); var https = require('https') var bodyParser = require("body-pa
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()
使用回调函数作为参数。然后可以使用该回调函数触发对dark sky的调用
var express=require('express');
var https=require('https')
var bodyParser=require(“主体解析器”);
var-app=express();
app.use(bodyParser.urlencoded({
扩展:正确
}));
use(bodyParser.json());
app.post(“/”,函数(请求,恢复,下一步){
var search=req.body.search;
//让google()将回调函数作为参数
//完成后,使用数据调用该函数。
谷歌功能(cb){
var api=“api-KEY”;
var url=https.get(`https://maps.googleapis.com/maps/api/geocode/json?address=${search}&key=${api}`,函数(res3){
var body=“”;
谷歌结果;
res3.on('data',函数(data){
body+=data.toString();
})
res3.on('end',function(){
googleResults=JSON.parse(body);
//控制台日志(主体);
lat=googleResults.results[0].geometry.location.lat;
lon=googleResults.results[0].geometry.location.lon;
//在这里调用函数
cb(lat,lon);
})
});
}
//现在使用回调对darksky执行第二个请求
谷歌(功能(lat、lon){
//将C连接到API URL()
var request=https.get(`https://api.darksky.net/forecast/API-KEY/${lon},${lat}`,函数(res2){
console.log(lon+“”+lat)
var body=“”;
天气变化;
//读取数据
res2.on('data',函数(data){
body+=data.toString();
})
res2.on('end',function(){
//解析数据
weather=JSON.parse(body);
//打印数据
//console.log(“test=“+天气.当前.温度”)
res.render('索引'{
温度:天气,
湿度:天气。当前。湿度,
风:天气。当前。风速
});
})
});
}});
});代码>在这里利用NodeJS的异步特性(使用节点样式的回调、承诺等)
例如,只需在google
函数中添加一个回调参数,在启动回调之前不要运行http请求。例如,您的google函数可以变成以下函数,然后调用google并在回调中运行以下代码:
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
})
注意:我建议传递参数或在回调中返回lat
和lon
,而不是使用lat
和lon
拖出全局范围,但这仍然有效。这不是解决问题的最简单或最容易的方法,但是我一直在使用await
关键字和节点fetch
库来执行这类请求
基本上,node fetch
在承诺上工作,这意味着您可以使用它发出请求,并在请求完成后使用.then()
执行某些操作。wait
关键字将所有嵌套转换为类似同步的代码,这意味着它更易于阅读和维护。下面是使用它们时代码的外观:
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的一部分,您可能需要在较旧的浏览器上运行它。您无法使它同步!一个选择是只有在google结果完成后才调用weather api。你在这篇文章中发布了你的api密钥,它在编辑中被删除了,但它仍然被公开。您应该撤销它并重新颁发一个新密钥。@Adam,谢谢,我已经这样做了,在发布之前应该仔细检查一下。您在这篇文章中发布了您的API密钥,它在编辑时被删除了,但它仍然被公开。你应该撤销它并重新发布一个新的密钥。哦,我复制它时,他最初发布了他的API密钥。哦,我查看了你的解决方案,但没有看到。谢谢。@JordanS谢谢你工作得很好,我还请求了新的api密钥。学童错误。还将更详细地研究回调。