Promise在asynchronous操作完成之前parsing

我想调用Google Maps API并使用结果调用另一个API(这是我的最终目标,现在我只想将结果打印到控制台)。我的问题是,promise在API之前解决调用,并最终导致未定义的结果。

routes.js

const express = require('express'); const router = express.Router(); const geospacial = require('./geospacial.js'); const trailapi = require('./trailapi.js'); router.get('/', (req, res, next) => { res.render('index'); }); router.post('/', (req, res, next) => { let activity = req.body.activity; let radius = req.body.radius; let getUserCoords = new Promise((resolve,reject) => { let userCoords = geospacial.getCoords(req.body.zip); resolve(userCoords); }); getUserCoords.then((result) => { console.log("data: " + result); }); }); module.exports = router; 

Google Maps API(geospacial.js)

 const https = require('https'); require('./env.js'); // comment out for production // Source: https://gist.github.com/clauswitt/1604972 const getDistance = (start, end) => { const earthRadius = 6371.008; let lat1 = parseFloat(start.latitude); let lat2 = parseFloat(end.latitude); let lon1 = parseFloat(start.longitude); let lon2 = parseFloat(end.longitude); let dLat = (lat2 - lat1) * Math.PI / 180; let dLon = (lon2 - lon1) * Math.PI / 180; lat1 = lat1 * Math.PI / 180; lat2 = lat2 * Math.PI / 180; let a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); let d = earthRadius * c; let kilometers = Math.round(d * Math.pow(10, 2)) / Math.pow(10, 2); let miles = Math.round(kilometers * .621371); console.log(miles); return miles; }; // getDistance({latitude: 39.72122192, longitude: -80.51956177},{latitude: 40.02198029, longitude: -79.90330505}); // for testing const getCoords = (addressData) => { let body = ''; let req = https.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + addressData + '&key=' + process.env.googleAPIKey, function(res) { res.on('data', function(data) { body += data; }); res.on('end', function() { let result = JSON.parse(body); let coords = result.results[0].geometry.location; console.log(coords); return coords; }); }); req.on('error', function(e) { console.error(e); }); }; // getCoords('15351'); // for testing module.exports = { getCoords: getCoords, getDistance: getDistance }; 

getCoords有一个asynchronous调用,所以你在getCoords返回一个值之前解决承诺。 您需要解决asynchronous函数callback中的承诺。

let getUserCoords = geospacial.getCoords(req.body.zip);

 const getCoords = (addressData) => { // getCoords returns a promise return new Promise(function(resolve, reject) { let body = ''; let req = https.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + addressData + '&key=' + process.env.googleAPIKey, function(res) { res.on('data', function(data) { body += data; }); res.on('end', function() { let result = JSON.parse(body); let coords = result.results[0].geometry.location; console.log(coords); resolve(coords); // promise resolves inside the callback of your async function }); req.on('error', function(e) { reject(e); console.error(e); }); }); }) }; // getUserCoords now holds the returned promise and will fire .then() when the promise is resolved getUserCoords.then(function(coords) { console.log(coords); }); 

getCoords不返回一个承诺,所以它不起作用。 也许你可以像这样改变它:

 const getCoords = (addressData) => { return new Promise((resolve, reject) => { let body = ''; let req = https.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + addressData + '&key=' + process.env.googleAPIKey, function(res) { res.on('data', function(data) { body += data; }); res.on('end', function() { let result = JSON.parse(body); let coords = result.results[0].geometry.location; console.log(coords); resolve(coords); }); }); req.on('error', function(e) { console.error(e); reject(e) }); }) }; 

你的getCoords函数有一个缺陷:它永远不会返回任何东西。 永远。

https.get是asynchronous的, req.on也是asynchronous的。 所以你在getCoords做两个asynchronous操作,但是永远不会返回任何东西。

可能会认为'end'事件处理程序中的return语句返回getCoords ,但不是。 位于事件处理程序中的返回返回事件处理程序函数(该函数在“ res.on('end', ”)之后启动。

不用担心,你走在正确的轨道上。 用Promise

 const getCoords = (addressData) => { return new Promise((resolve, reject) => { // do your stuff // when you want to return a value, resolve: resolve(apiResponse); }); }; 

现在getCoords会返回一个Promise!

你的代码打印出来的响应现在应该看起来像这样:

 geospacial.getCoords(req.body.zip).then((result) => { console.log("data: " + result); }); 

哪一个

  1. 调用geospacial.getCoords
  2. then调用由此产生的Promise
  3. (最终)解决并打印出你的结果!