javascript - 防止方法在 Meteor 的服务器上自动运行

标签 javascript meteor coffeescript geocoding

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

我的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' } ]

关于javascript - 防止方法在 Meteor 的服务器上自动运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46519445/

相关文章:

javascript - 更改链接 URL 中的路径名,同时保持查询字符串不变

javascript - JS窗口宽度html5视频元素响应

javascript - Meteor:排队任务中出现异常:错误:无法在 'removeChild' 上执行 'Node' :要删除的 Node 不是此 Node 的子 Node

jquery 大师,jquery 扩展并没有克隆 dom 元素

javascript - JavaScript 输出中的 CoffeeScript 注释

javascript - 如何在不带引号的情况下将值放入 JSONObject

javascript - Bootstrap modal 使滚动条在关闭后消失

javascript - MongoDB - 查找今天之前和之后的单个日期

maven-2 - 使用 maven 的自定义编译器

javascript - jquery 使用复选框来切换同一个 div 中的元素