Google maps 在非异步上下文中使用回调

Google maps 在非异步上下文中使用回调,google-maps,ember.js,Google Maps,Ember.js,我有一个名为“getGmapsDistance()”的服务。在这里,我使用谷歌地图api获取起点和终点之间的距离 export default Ember.Service.extend({ getShortestDistanceInMeters: function(location) { var service = new google.maps.DistanceMatrixService(); service.getDistanceMatrix({ ...

我有一个名为“
getGmapsDistance()
”的服务。在这里,我使用谷歌地图api获取起点和终点之间的距离

export default Ember.Service.extend({

  getShortestDistanceInMeters: function(location) {

    var service = new google.maps.DistanceMatrixService();

    service.getDistanceMatrix({
      ...
    }, this.callback); //<<<<<< !!!

  },

  callback: function(response, status) {
      ....
  }
});
locationsNearby: Ember.computed('locations', function() {
     //...
     var filteredResult = [];

      locations.forEach(function(locat) {
        if (this.get('distanceService').getShortestDistanceInMeters(locat) <= maxDistance) {
          filteredResult.pushObject(locat);
        }
      });

      return filteredResult;
})
导出默认Ember.Service.extend({
getShortestDistanceInMeters:函数(位置){
var service=new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
...

},this.callback);//您不能使异步调用同步!这是javascript语言的一个限制,必须理解!javascript只有一个线程,因此不能由库或其他程序更改

处理回调的新方法是承诺。 你真的应该结账! 这是你读过的最漂亮的说明书之一

Ember大量使用承诺!例如,routes
model
hook在继续转换之前等待承诺的解析

在您的情况下,您希望在承诺解析时更新computed属性。因为余烬数据经常导致这种情况发生,所以它们提供了两个奇特的类:PromiseObject和PromiseArray。依赖于返回PromiseObject/数组的computed属性的computed属性将在承诺解析时重新计算:

locationsNearby: Ember.computed('locations', {
    get() {
        let promise = Ember.RSVP.all(this.get('locations').map(location => Ember.RSVP.hash(({
            location,
            distance: this.get('distanceService').getShortestDistanceInMeters(location)
        })))).then(hashs => hashs.filter(hash => hash.distance <= maxDistance).map(hash => hash.location));

        return DS.PromiseArray.create({promise});
    }
})
然后,我对所有这些函数使用
RSVP.hash
,以获得一个承诺数组,该数组将解析为一个具有距离和位置的哈希数组:

let hashPromiseArr = locationsWithDistancePromise.map(h => Ember.RSVP.hash(h));
现在,我使用
Ember.RSVP.all
获得一个承诺,该承诺将解析为一个包含位置和距离的哈希数组:

let locationsWithDistancePromise = this.get('locations').map(location => {
  distance: this.get('distanceService').getShortestDistanceInMeters(location),
  location
})
let hashArrPromise = Ember.RSVP.all(hashPromiseArr);
最后我
。然后在promise上
,并过滤附近的位置。我还将哈希映射到一个位置数组

let promise = hashArrPromise.then(hashs => {
  return hashs.filter(hash => hash.distance <= maxDistance)
    .map(hash => hash.location);
});

您可以使用
{{{each}}
从把手循环这个计算属性,或者在另一个计算属性中使用它:

allNearbyLocations: Ember.computed('locationsNearby.[]', {
    get() {
        return this.get('locationsNearby').toArray().join(' - ');
    }
}

当然,您需要重写
getshortdistanceinmeters
,以便它返回一个承诺:

getShortestDistanceInMeters(location) {
    var service = new google.maps.DistanceMatrixService();

    return new Ember.RSVP.Promise((resolve, reject) => {
        service.getDistanceMatrix({
          //...
        }, (response, status) => {
            if(status.error) {
                reject(response);
            } else {
                resolve(response);
            }
        });
    });
}

您不能使异步调用同步!这是一个javascript语言限制,必须理解!javascript只有一个线程,因此不能由库更改

处理回调的新方法是承诺。 你真的应该结账! 这是你读过的最漂亮的说明书之一

Ember大量使用承诺!例如,routes
model
hook在继续转换之前等待承诺的解析

在您的情况下,您希望在承诺解析时更新computed属性。因为余烬数据经常导致这种情况发生,所以它们提供了两个奇特的类:PromiseObject和PromiseArray。依赖于返回PromiseObject/数组的computed属性的computed属性将在承诺解析时重新计算:

locationsNearby: Ember.computed('locations', {
    get() {
        let promise = Ember.RSVP.all(this.get('locations').map(location => Ember.RSVP.hash(({
            location,
            distance: this.get('distanceService').getShortestDistanceInMeters(location)
        })))).then(hashs => hashs.filter(hash => hash.distance <= maxDistance).map(hash => hash.location));

        return DS.PromiseArray.create({promise});
    }
})
然后,我对所有这些函数使用
RSVP.hash
,以获得一个承诺数组,该数组将解析为一个具有距离和位置的哈希数组:

let hashPromiseArr = locationsWithDistancePromise.map(h => Ember.RSVP.hash(h));
现在,我使用
Ember.RSVP.all
获得一个承诺,该承诺将解析为一个包含位置和距离的哈希数组:

let locationsWithDistancePromise = this.get('locations').map(location => {
  distance: this.get('distanceService').getShortestDistanceInMeters(location),
  location
})
let hashArrPromise = Ember.RSVP.all(hashPromiseArr);
最后我
。然后在promise上
,并过滤附近的位置。我还将哈希映射到一个位置数组

let promise = hashArrPromise.then(hashs => {
  return hashs.filter(hash => hash.distance <= maxDistance)
    .map(hash => hash.location);
});

您可以使用
{{{each}}
从把手循环这个计算属性,或者在另一个计算属性中使用它:

allNearbyLocations: Ember.computed('locationsNearby.[]', {
    get() {
        return this.get('locationsNearby').toArray().join(' - ');
    }
}

当然,您需要重写
getshortdistanceinmeters
,以便它返回一个承诺:

getShortestDistanceInMeters(location) {
    var service = new google.maps.DistanceMatrixService();

    return new Ember.RSVP.Promise((resolve, reject) => {
        service.getDistanceMatrix({
          //...
        }, (response, status) => {
            if(status.error) {
                reject(response);
            } else {
                resolve(response);
            }
        });
    });
}

您可以从
getShortestDistanceInMeters
方法返回承诺,签出您可以从
getShortestDistanceInMeters
方法返回承诺,签出感谢@Lux的这种大方法,但我认为它不起作用:据我所知,getShortestDistanceInMeters函数没有“等待”机制(因为它会立即返回“nothing”,并且只有异步回调函数会从google得到答案)。因此,在您的解决方案中,承诺将立即实现,因为它的返回将不包括api请求的结果。对吗?我已编辑了答案。当然,您必须重写
GetShortDistanceInMeters
,因此它将返回一个承诺。非常感谢,到目前为止这非常有用!但它仍然无法100%工作。在我的回答中,console.out正在工作,但不在模板中。请查看以下要点:您能再帮我处理最后一部分吗?:)第21行缺少
return
。或者省略花括号。因为
x=>1
返回1,并且与
x=>{return 1}
相同,但是
x=>{1}
将返回
未定义的
!并且您需要
PromiseArray
来制作一个合适的数组,以便在
把手
模板中循环。PromiseArray首先是一个空数组,稍后将更新为已解析的数组。先生,您太棒了!非常感谢@Lux!感谢@Lux的这种大方法,但我认为它是有效的nt工作:据我所知,他们的getShortestDistanceInMeters函数没有“等待”机制(因为它会立即返回“nothing”,只有异步回调函数会从google得到答案)。因此,在您的解决方案中,承诺将立即实现,因为它的返回将不包括api请求的结果。对吗?我已编辑了答案。当然,您必须重写
GetShortDistanceInMeters
,因此它将返回一个承诺。非常感谢,到目前为止这非常有用!但它仍然无法100%工作。在我的回答中,console.out正在工作,但不在模板中。请查看以下要点:您能再帮我处理最后一部分吗?:)第21行缺少
return
。或者省略花括号。因为
x=>1
返回1,并且与
x=>{return 1}
相同,但是
x=>{1}
将返回
未定义的
!并且您需要
PromiseArray
来创建一个可在
han中循环的宜人数组