从辅助函数异步返回值?

时间:2015-03-15 03:25:06

标签: javascript meteor

getCurrentPosition()是异步的,那么如何从帮助器返回一个值?

Template.pos.helpers({
    'nearestLocation': function() {
        var location = undefined;

        if('geolocation' in navigator) {
            navigator.geolocation.getCurrentPosition(function(position) {

                location = Locations.findOne({
                    geolocation: {
                        $near: {
                            $geometry: {
                                type: 'Point',
                                coordinates:[153.0415850, -27.4477160]
                            }, 
                            $maxDistance: 500
                        }
                    }
                });

                console.log(location.name);

                return location.name;
            });
        }
    }
});

该查找工作正常,因为控制台确实输出了正确的结果。我错过了关于Meteor工作方式我应该知道的事情吗?

3 个答案:

答案 0 :(得分:1)

如果以异步方式检索值,则无法直接从函数返回值。该函数在检索到异步值之前返回。

解决此问题的常用方法是将回调传递给函数,然后主机函数调用回调并在检索到它时将值传递给它。

如果在您使用的基础架构中,nearestLocation函数必须是同步的(例如,它不能使用回调或返回稍后会返回值的承诺),那么您&#39因为你无法在Javascript中从同步界面返回异步值,所以有点不走运。它无法完成。

我所知道的唯一可能的解决方法是以某种方式预测在需要之前需要什么值,以便您可以异步检索所需的值,将其存储起来,然后在为值创建同步请求时,它只能被返回,因为它之前已被检索过。

这需要先了解所要求的内容,并提前有足够的时间在需要之前实际检索它。

答案 1 :(得分:1)

比回调模式稍微好一点的方法是从函数返回一个promise对象,它有一个then()方法,在解析时被调用,所以你可以将响应的处理程序链接到请求上,如:

getCurrentPosition().then(function(result) {});

Promise本身就是在ES6中出现的,但是你今天使用它们,你必须使用一个专门用于承诺的转换器或库,例如q

答案 2 :(得分:1)

如果/找到位置,只需使用Session变量或其他反应数据源强制帮助程序重新运行:

Template.pos.helpers({
  nearestLocation: function() {
    var position = Session.get('position');

    // only bother doing the find if the position is set
    if (position) {
      // use position in the find
      var location = Locations.findOne(...);
      return location.name;
    }
  }
});

Template.post.rendered = function() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      // set the session variable when/if position is found
      Session.set('position', position);
    });
  }
};