如何在ng-repeat中使用异步地理位置值?

时间:2016-06-18 13:11:38

标签: javascript angularjs meteor geolocation ng-repeat

JS noob在这里。

我正在尝试构建一个应用程序(使用Angular-Meteor),列出周围的餐馆,我的一个视图应该显示每个餐厅,您当前位置和该餐厅之间的距离。我在为每家餐馆执行计算时遇到问题,然后在视图中显示该值。

使用我当前的代码,页面顶部加载,然后函数(distanceToPlace)我调用每个地方调用然后加载完成,最后我可以看到具有正确距离值的元素。 / p>

存在多个问题:

  • 每个餐厅不止一次调用地理定位API,我无法弄明白为什么(我在数据库中有50家餐馆,有时我看到我的控制台日志检查打印2000次以上)

  • 即使每个餐厅​​只调用一次,也会非常低效。应该有一种方法在页面加载时只调用一次,然后只对每个餐馆的数据进行距离计算。更好的是,我的整个应用程序应该有某种全局变量,其中包含我可以从任何页面访问的用户位置(刷新每X秒)。

此外,我希望能够在计算完成后按距离对餐馆进行排序,但我不知道如何解决这个问题:(

这是JS(控制器内部):



        var userLng = '';
        var userLat = '';
        this.loaded = false;
        var that = this;

        //Calculate the distance with coordinates
        function getDistanceFromLatLonInKm(lon1,lat1,lon2,lat2) {
            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
            return d;
        }

        //Calculation sub-formula
        function deg2rad(deg) {
            return deg * (Math.PI/180)
        }

        //Find user's location then start the distance calculation
        this.distanceToPlace = function(placeLng, placeLat) {
            navigator.geolocation.getCurrentPosition(function(position) {
                userLng = Math.round(position.coords.longitude * 1000000) / 1000000;
                userLat = Math.round(position.coords.latitude * 1000000) / 1000000;
                that.loaded = true;
                console.log('Done');
                return Math.round(getDistanceFromLatLonInKm(userLng, userLat, placeLng, placeLat) * 1000);
            });
        };




以下是观点:



<md-content flex ng-show="placeSearch.loaded">
  <md-card ng-repeat="place in placeSearch.places | eventDayFilter:placeSearch.eventDay | placeAreaFilter:placeSearch.area | eventTimeFilter:placeSearch.eventTime:placeSearch.eventDay | orderBy:placeSearch.sort">
    <md-card-title>
      <md-card-title-media>
        <div class="md-media-md card-media">
          <img src="https://pbs.twimg.com/profile_images/611558188744372225/VoCVrXWX.png">
        </div>
      </md-card-title-media>
      <md-card-title-text>
        <span class="md-subhead" ui-sref="placeDetails({ placeId: place._id, lastPage: 'search' })">
                        {{place.name}}
                    </span>
        <small>{{place.events[placeSearch.eventDay].begin}}h-{{place.events[placeSearch.eventDay].end}}h:</small>
        <span class="md-body-1">{{place.events[placeSearch.eventDay].description}}</span>
        <span flex></span>
        <div layout="row" layout-align="space-between end">
          <span class="md-caption">
                            <md-icon md-svg-icon="action:ic_room_24px"></md-icon>
                            <span ng-if="distance=placeSearch.distanceToPlace(place.address.lon, place.address.lat)">{{distance}} m</span>
          </span>
          <md-icon class="icon-fav" md-svg-icon="action:ic_favorite_border_24px"></md-icon>
        </div>
      </md-card-title-text>
    </md-card-title>
  </md-card>
</md-content>
&#13;
&#13;
&#13;

我使用&#34; ng-if&#34;在那里,但我不太确定它是否是正确的方法。 提前谢谢!

1 个答案:

答案 0 :(得分:0)

以下是我将如何处理此问题:

  1. 我会创建一个返回餐馆光标的出版物
  2. 该出版物将具有单个参数,即具有用户当前坐标的对象
  3. 我会_.throttle()该出版物,使其每N秒运行速度不超过一次(如果用户快速移动)
  4. 我会在发布中运行geoquery,因为Meteor不支持客户端上的mongodb地理查询,只在服务器上支持。
  5. 然后我从客户端订阅该出版物,传递用户的当前位置
  6. 我可能仍然在客户端进行距离计算,并在那里进行排序,在一个帮助器中返回一个餐馆对象数组,并附加一个额外的距离键。
  7. 然后您的角度代码可以处理显示您想要的餐馆对象
  8. 当您完成上述所有代码的工作和调试后,您可能会感觉很高,也可以删除您的js noob徽章。
  9. 计算单个餐厅助手的距离是没有意义的,因为它是一个排序键 - 您希望在帮助器中执行它,返回整个列表/餐馆阵列。此外,就像你目睹的那样,个人助手的运行频率超出了你的预期。