Javascript Api数据与Node.js异步并检索数据使其同步

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

我需要一个我正在制作的节点天气应用程序的帮助。我使用GoogleAPI获取地址的经度和纬度,并将其输入DarkSkyAPI,以JSON格式返回天气

我的问题是,大多数情况下,天气API在google API返回经度和纬度之前进行搜索。我知道它为什么这样做是因为Node的异步特性。我的问题是如何使此部件同步

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密钥。学童错误。还将更详细地研究回调。