简体   繁体   中英

Loopback Geopoint Hook not persisting change

I created a before save hook in my loopback api app. My location model has an address and a latlng geopoint

  "properties": {
    "name": {
      "type": "string"
    },
    "address": {
      "type": "string"
    },
    "latlng": {
      "type": "geopoint"
    }
  },

Within my common\\models\\location.js I have the following code:

var https = require('https');
var loopback = require('loopback');
module.exports = function(Location) {
  Location.observe('before save', function(ctx, next) {
    let path = `/maps/api/geocode/json?address=${ctx.instance['address']}&key=AIzaSyCWk3ePB8idTw74LyhR8tLSCmVgbZDKiIQ`
    console.log(path);
    https.get({
      hostname: 'maps.googleapis.com',
      path: encodeURI(path)
    }, (res) => {
      var body = [];
      res.on('data', (d) => {
        body.push(d)
      })
      res.on('end', () =>{
        body = JSON.parse(Buffer.concat(body).toString());
        let latlng = new loopback.GeoPoint({
          lat: body['results'][0]['geometry']['location']['lat'],
          lng: body['results'][0]['geometry']['location']['lng']
        })
        console.log(latlng)
        if (ctx.instance) {
          ctx.instance.latlng = latlng;
        } else {
          ctx.data.latlng = latlng;
        }
      })
    })
     next();
  })
};

What I'm expecting this code to do is to make an http(s) request to google maps, return the latitude and longitude of the address, naively predict the first entry correct and persist that data to my model in the latlng property. I am currently correctly outputting to the console the expected latitude and longitude as a GeoPoint object:

GeoPoint { lat: 42.3675294, lng: -71.18696609999999 }

How can I update my model with this information? I've tried to remove the conditional if (ctx.instance) with no difference. I've tried using a different object notation:

ctx.instance['latlng']=latlng

No errors are being logged. I'm persisting with MongoDB, but the problem is the same using in-memory db. Additional code located on Github.com/andygauge/api.socialconnect

The problem here is the placement of next() . Due to the asynchronous nature of nodejs, next() was called before the http request completed and processed. The changes to the model occur after the workflow proceeds to validation.

The solution looks like this:

module.exports = function(Location) {
  Location.observe('before save', function(ctx, next) {
    let path = `/maps/api/geocode/json?address=${ctx.instance['address']}&key=AIzaSyCWk3ePB8idTw74LyhR8tLSCmVgbZDKiIQ`
    console.log(path);
    https.get({
      hostname: 'maps.googleapis.com',
      path: encodeURI(path)
    }, (res) => {
      var body = [];
      res.on('data', (d) => {
        body.push(d)
      })
      res.on('end', () =>{
        body = JSON.parse(Buffer.concat(body).toString());
        let latlng = new loopback.GeoPoint({
          lat: body['results'][0]['geometry']['location']['lat'],
          lng: body['results'][0]['geometry']['location']['lng']
        })
        console.log(latlng)
        if (ctx.instance) {
          ctx.instance.latlng = latlng;
        } else {
          ctx.data.latlng = latlng;
        }
        next();
      })
    })
  })
};

Thank you for the views.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM