You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 2中如何从GeoFire异步方法返回自定义对象数组Promise

解决GeoFire异步场景下返回Vendor对象数组的问题

首先,你的核心问题在于GeoFire的key_entered是异步事件驱动的——它会在查询到匹配位置时多次触发,而非一次性返回所有结果。直接在事件回调里创建Vendor对象,没法让外层的Promise正确返回完整数组。我们需要把这些异步结果统一收集,等查询完成后再resolve这个Promise。

下面是修正后的完整实现思路和代码:

步骤1:用Promise包裹整个查询流程

在函数内部返回一个新的Promise,把GeoFire的事件监听、结果收集、完成逻辑都放在这个Promise里处理。

步骤2:监听key_entered收集Vendor对象

每次触发key_entered时,创建对应的Vendor实例并添加到数组中。

步骤3:监听ready事件完成Promise

GeoFire的ready事件会在初始查询完成(所有匹配的键都已触发key_entered)时触发,这时我们就可以resolve收集到的Vendor数组,同时记得移除事件监听避免内存泄漏。

完整代码示例

getLocations(radius: number, coords: Array<number>): Promise<Vendor[]> {
  console.log('In get locations');
  return new Promise((resolve, reject) => {
    const geoQuery = this.geoFire.query({ center: coords, radius: radius });
    const vendors: Vendor[] = [];

    // 监听key_entered,收集Vendor对象
    const keyEnteredListener = geoQuery.on('key_entered', (key, location, distance) => {
      console.log(`key ${key} distance ${distance}`);
      const vendor = new Vendor();
      // 根据业务需求给Vendor赋值,比如ID、位置、距离等
      vendor.id = key;
      vendor.location = location;
      vendor.distance = distance;
      // 其他属性初始化...
      vendors.push(vendor);
    });

    // 监听ready事件,查询完成后返回结果
    const readyListener = geoQuery.on('ready', () => {
      // 移除监听,避免内存泄漏
      keyEnteredListener.cancel();
      readyListener.cancel();
      // 返回收集到的所有Vendor
      resolve(vendors);
    });

    // 监听错误事件,处理异常情况
    const errorListener = geoQuery.on('error', (error) => {
      // 清理所有监听
      keyEnteredListener.cancel();
      readyListener.cancel();
      errorListener.cancel();
      // 抛出错误
      reject(error);
    });
  });
}

额外注意事项

  • 内存泄漏问题:必须在查询完成或出错时调用监听的cancel()方法,否则这些监听器会一直驻留内存。
  • 实时更新场景:如果需要实时获取后续进入查询范围的新Vendor,ready事件只代表初始查询完成,后续key_entered还会触发。这种情况建议用Observable替代Promise,或者在函数里额外处理实时更新逻辑。
  • Vendor详情补全:如果需要从Firebase数据库根据key获取Vendor的详细信息(比如名称、联系方式),可以在key_entered回调里用async/await处理异步请求,示例如下:
const keyEnteredListener = geoQuery.on('key_entered', async (key, location, distance) => {
  console.log(`key ${key} distance ${distance}`);
  // 假设你有一个获取Vendor详情的异步方法
  const vendorDetails = await this.fetchVendorDetails(key);
  const vendor = new Vendor();
  vendor.id = key;
  vendor.location = location;
  vendor.distance = distance;
  vendor.name = vendorDetails.name;
  vendor.contact = vendorDetails.contact;
  vendors.push(vendor);
});

这种情况下,ready事件触发时可能有些详情请求还没完成,需要用Promise.all等待所有异步请求结束后再resolve数组,调整逻辑即可。

内容的提问来源于stack exchange,提问作者kpvsrkp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:23:53