在 Meteor 的服务器上自动阻止 运行 方法

Prevent method from running automatically on server in Meteor

我试图在服务器文件夹中创建地理编码方法,但它抱怨页面加载时未定义地址。看起来该方法在输入具有值(或已被调用)之前在页面加载时触发并导致此行为。有没有办法让方法等待 运行 直到被调用而不是自动调用,或者解决这个问题的其他方法? Aldeed:geocoder 似乎只 运行 服务器端。

我的 coffeescript 方法,使用 aldeed:geocoder

geocodeAddress: (address) ->
lat = ''
lng = ''
    addressVar = ''
    geocoder = new GeoCoder(
      geocoderProvider: 'google'
      httpAdapter: 'https'
      apiKey: 'AIzaSyDYjLGrETRt4hPZtXcmzQwRbzlFT1zWwr8')
    geocoder.geocode { 'address': address }, (results, status) ->
        if status == google.maps.GeocoderStatus.OK
          lat = results[0].geometry.location.lat()
          lng = results[0].geometry.location.lng()
            return [lat,lng]

模板事件

Template.dashboard.events({
  'click #customlocationsubmit'(evt) {
    if (document.getElementById("customlocation")) {
      customLocationValue = document.getElementById("customlocation").value;
    }
    if (typeof customLocationValue === 'undefined' || customLocationValue == "") {
        return false;
    } else {
    customUserLocation = Meteor.call('geocodeAddress',customLocationValue);
  }
  }
});

模板

<template name="dashboard">
    <div class="template-dashboard">
        <div class="container">
            <div class="row">
                <div class="col-md-3">
                    {{> addPost}}
                    {{> favoritesSidebar}}
                </div>
                <div class="col-md-9">
                <button id="customlocationsubmit" type="submit" class="btn btn-primary">Update</button>

                    {{> posts}}
                </div>
            </div>
        </div>
    </div>
</template>

styx 的点击事件再次更新

'click #customlocationsubmit'(evt) {
    if (document.getElementById("customlocation")) {
      customLocationValue = document.getElementById("customlocation").value;
    }
    if (typeof customLocationValue === 'undefined' || customLocationValue == "") {
        return false;
    } else {
    Meteor.call('geocodeAddress', customLocationValue, (err, result) => {
    if (err) {
      // handle error
      return;
    }
    const [ lat, lng ] = result;
    geoResult = result;
    const sortOrder = (Session.get('posts.sortBy') || {}).date || 1;
    return Session.set('posts.sortBy', {date: -sortOrder});
    return distanceFilter(this, geoResult );
  });
  }

  },

styx 的辅助函数

distanceFilter(location,customUserLocation) {
    function getDistanceFromLatLonInMi(lat1,lon1,lat2,lon2) {
      var R = 6371; // Radius of the earth in km
      var dLat = deg2rad(lat2-lat1);  // deg2rad below
      var dLon = deg2rad(lon2-lon1);
      var a =
        Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
        Math.sin(dLon/2) * Math.sin(dLon/2)
        ;
      var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
      var d = R * c; // Distance in km
      var e = d * 0.621371;
      return e;
    };

    function deg2rad(deg) {
      return deg * (Math.PI/180);
    };

    getUser = Meteor.users.findOne({
      _id: Meteor.userId()
    });
    if (getUser){
    userUserName = getUser.username;
    userLocation = getUser.profile.location.split(',');
    };
    eventLocation = location.split(',');
    if (typeof customLocationValue === 'undefined' || customLocationValue == "") {
      customUserLocationVar = userLocation;
    }
      else {
        customUserLocationVar = customUserLocation;
        console.log(customUserLocation);
      }
    distance = getDistanceFromLatLonInMi(customUserLocationVar[0],customUserLocationVar[1],eventLocation[0],eventLocation[1]);
    eventDistance = Math.round(distance);
    filterValue = jQuery('#eventdistance').val();
    if (filterValue) {
      if (eventDistance <= filterValue) {
        return true;
        }
    } else if (eventDistance <= 20) {
          return true;
    } else {
          return false;
    }

  },

使用 aldeed:geocoder Meteor 包有两个问题(还有一个问题):

  1. 来自package documentation:

    Geocoding an address is simple. Get a new instance of GeoCoder and then call the geocode method on it, passing in the address string.

    这意味着,与 npm 包不同,geocode() 函数期望第一个参数是一个字符串 — 您要进行地理编码的地址 (source code)

  2. 来自同一文档:

    Note that unlike in the node package, the geocode method is synchronous. This makes it simple to use in a server method. If you prefer to pass a callback as the last argument, you can.

    这意味着,您的服务器方法可以(并且应该)利用:

    geocodeAddress: (address) ->
      geocoder = new GeoCoder
        httpAdapter: 'https'
        apiKey: 'AIzaSyDYjLGrETRt4hPZtXcmzQwRbzlFT1zWwr8'
    
      result = geocoder.geocode(address).pop()
    
      [ result.latitude, result.longitude ]
    
  3. 正如 Michel Floyd 在评论中指出的那样,客户端上的 Meteor.call 异步的 ,因此您应该这样做:

    Meteor.call('geocodeAddress', customLocationValue, (err, result) => {
      if (err) {
        // handle error
        return;
      }
      const [ lat, lng ] = result;
      // handle success
    });
    

添加:来自geocode(address)的响应(从meteor shell执行):

> g.geocode('02068, Ukraine, Kiev')
[ { formattedAddress: 'Kiev, Ukraine, 02000',
    latitude: 50.4501,
    longitude: 30.5234,
    extra: 
     { googlePlaceId: 'ChIJBUVa4U7P1EARxX1LbAvqE6A',
       confidence: 0.5,
       premise: null,
       subpremise: null,
       neighborhood: null,
       establishment: null },
    administrativeLevels: { level2long: 'Kyiv City', level2short: 'Kyiv City' },
    zipcode: '02000',
    city: 'Kiev',
    country: 'Ukraine',
    countryCode: 'UA' } ]