在异步操作完成之前解析Promise

时间:2017-05-04 02:21:45

标签: javascript node.js es6-promise

我想打电话给Google Maps API并使用结果来调用另一个API(这是我最终的目标,现在我只想将结果打印到控制台。)我的问题是承诺解决了在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
};

3 个答案:

答案 0 :(得分:2)

getCoords有异步调用,因此您在getCoords返回值之前解析promise。您需要在异步函数的回调中解决这个承诺。

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); 
});

答案 1 :(得分:1)

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)
      });

  })

};

答案 2 :(得分:1)

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

https.get是异步的,req.on也是异步的。因此,您在getCoords中执行了两次异步操作,但从不返回任何内容。

可能认为'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. 调用生成的Promise' then
  3. (最终)解析并打印出你的结果!
相关问题