2017-05-04 26 views
1

私は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 
}; 
+0

'new Promise'は' getUserCoords'ではなく 'getCoords'で行うべきです。非同期コールバックの 'return'は機能しません。 – Bergi

答えて

2

getCoords getCoordsが値を返す前に、あなたが約束を解決しているように、非同期呼び出しを持っています。あなたは、非同期関数のコールバックで約束を解決する必要があります。

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

エラーハンドラをインストールする前に 'return'してください。約束エグゼクティブのコールバックの中に入れて、それが起こったときに '拒否 'してください。 – Bergi

+0

おっと、誤植を編集します –

+0

これはまさに私が必要としていたものです。ありがとうございました!私はまだ約束のまわりで頭を抱えようとしています。 – SmellydogCoding

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

    }) 

}; 
1

あなたgetCoords機能は、欠陥を持っている:それは何かを返すことはありません。これまで

https.getは非同期で、req.onも非同期です。つまり、getCoordsでは2つの非同期操作を行いますが、何も返すことはありません。

あなた'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は約束を返すでしょう!

次のように少し見えるはずです、それの応答をプリントアウトするというあなたのコード:geospacial.getCoords

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

    1. コールは、結果Promisethen
    2. (最終的に呼び出します。 )あなたの結果を解決して印刷します!
  • 関連する問題