NodeJS geofire的最大调用堆栈错误(firebase-实时数据库)

tgabmvqs  于 2023-02-08  发布在  Node.js
关注(0)|答案(1)|浏览(104)

我使用真实的数据库作为firebase,我使用geofire javascript包从firebase获得附近的数据。但有时它会自动给出错误,如:

RangeError: Maximum call stack size exceeded
at ChildrenNode.isLeafNode (api/node_modules/firebase-admin/node_modules/@firebase/database-compat/dist/index.standalone.js:8956:50)
at ChildrenNode.equals (api/node_modules/geofire/dist/geofire/index.cjs.js:8461:24)

这是我使用geofire从firebase实时数据库查找附近事物的示例查询

while (some amount) { 
 geoDriverId = await(new Promise((resolve, reject) => {
try {
  geoDriverId = []
  geoDriverIds = []
  const geoQuery = config.firebase.table.query({
    center: [parseFloat(pick_up_latitude), parseFloat(pick_up_longitude)],
    radius: i
  })
  let listener = geoQuery.on("key_entered", (key, location, distance) => {
    geoDriverIds.push({ key, distance });
  });
  geoQuery.on("ready", (key, location, distance) => {
    listener.cancel();
    geoQuery.cancel();
    resolve(geoDriverIds);
    return;
  });
} catch (e) {
  console.log("e", e)
}
}))
}
db2dz4w8

db2dz4w81#

如果目的是轮询查询的初始结果,请考虑使用下面的方法(这实际上就是您在问题中提供的代码,经过清理并转换为一个方法):

// Executes a GeoFire query around the given center and returns only the initial results as a Promise.
function pollGeofireLocation(center: Geopoint, radius: number) {
  return new Promise(resolve => {
    const queryResults = [],
          geoQuery = config.firebase.table.query({ center, radius });

    geoQuery.on("key_entered", (key, location, distance) => {
      queryResults.push({ key, distance }); // consider storing location
    });

    geoQuery.on("ready", () => {
      geoQuery.cancel(); // unsubscribe all event listeners and destroy query
      // consider sorting queryResults before resolving the promise (see below)
      resolve(queryResults);
    });
  });
}

用法:

const pick_up_geopoint = [parseFloat(pick_up_latitude), parseFloat(pick_up_longitude)];
const results = await pollGeofireLocation(pick_up_geopoint, 10);
// results is an array of { key: string, distance: number } objects,
// in the order they were discovered by the query - not necessarily by distance

要按与中心点的距离对结果进行排序:

const pick_up_geopoint = [parseFloat(pick_up_latitude), parseFloat(pick_up_longitude)];
const nearbyDriverIDs = await pollGeofireLocation(pick_up_geopoint, 10);
// nearbyDriverIDs is an array of { key: string, distance: number } objects,
// in the order they were discovered by the query - not necessarily by distance

nearbyDriverIDs.sort(({ distance: a_dist }, { distance: b_dist }) => a_dist - b_dist);
// nearbyDriverIDs is now an array of { key: string, distance: number } objects,
// ordered by their distance from the center point, closest to furthest.
// nearbyDriverIDs[0], if present (nearbyDriverIDs may be empty!), is the closest driver

如果目的是仅查找最接近的结果,则可以使用以下方法逐步搜索结果:

// Executes a GeoFire query around the given center, performing an expanding search where the first result is returned in a Promise.
function findClosestResultToGeofireLocation(center: Geopoint, maxRadius: number, stepRadius: number = 5, startRadius: number = 0) {
  return new Promise((resolve, reject) => {
    const queryResults = [],
          geoQuery = config.firebase.table.query({
            center,
            radius: Math.min(maxRadius, startRadius || stepRadius) // if startRadius is provided, use its value, otherwise start at stepRadius
          });

    geoQuery.on("key_entered", (key, location, distance) => {
      queryResults.push({ key, distance }); // consider storing location
    });

    geoQuery.on("ready", () => {
      // found at least one result? return the closest one
      if (queryResults.length > 0) {
        geoQuery.cancel(); // unsubscribe all event listeners and destroy query
        const closest = queryResults
          .reduce((closest, result) => result.distance < closest.distance ? result : closest);
        resolve(closest);
        return;
      }

      // no results for search criteria and at max search radius? reject with an error
      if (geoQuery.radius() >= maxRadius) {
        geoQuery.cancel(); // unsubscribe all event listeners and destroy query
        reject(new Error(`No results found within ${maxRadius}km`));
        // could also use resolve(null);
        return;
      }

      // expand search area by increasing the radius by stepRadius kilometers,
      // stopping at maxRadius kilometers
      // note: you may want to add a delay before calling this
      geoQuery.updateCriteria({
        radius: Math.min(maxRadius, geoQuery.radius() + stepRadius)
      });
    });
  });
}

用法:

const pick_up_geopoint = [parseFloat(pick_up_latitude), parseFloat(pick_up_longitude)];
const closestDriverID = await findClosestResultToGeofireLocation(pick_up_geopoint, 25);
// closestDriverID will be the closest driver to pick_up_geopoint.
// With the above arguments, the search will try for drivers <5km away, then
// <10km away, then <15km away, then <20km away and then finally <25km away.
// If a driver is not in range, the returned promise will reject with an error.

相关问题