非现有节点上的一次(" child_added")不会失败但会超时

时间:2017-06-16 12:35:59

标签: javascript firebase-realtime-database google-cloud-functions

首先,我不确定是否存在真正的问题,但我想我会分享我的推理。

我使用Firebase作为数据库/后端,用于归档来自家中各种传感器的所有数据以及具有托管的酷图的UI。因此,每隔10分钟,我会推出各种房间的各种数据(温度,湿度,二氧化碳水平,照明......)。我有近3年的数据可用(所以我的基地有很多节点)

所以我的数据库结构是这样的:

root
  readings
    room_id
      GUID
        time
        temp
        hum
        lum

几年来,我在家中托管了一个PHP脚本,检查每个读数/ room_id中的最新项目是否具有不太旧的时间值(不超过11​​分钟)。几天前我把它翻译成了Firebase云功能,我得到了类似的东西:

exports.monitor = functions.https.onRequest((req, res) => {
  const tstamp = Math.floor(Date.now() / 1000);
  var sensors = ["r01", "r02", "r03", "r04", "r05"];
  var promiseArray = [];
  var result = {};
  for (var i = 0; i < sensors.length; i++) {
    console.log('Adding promise for ' + sensors[i]);
    promiseArray.push(admin.database().ref('/readings/' + sensors[i]).limitToLast(1).once("child_added"));
  }
  Promise.all(promiseArray).then(snapshots => {
    console.log('All promises done : ' + snapshots.length);
    res.set('Cache-Control', 'private, max-age=300');
    for (var i = 0; i < snapshots.length; i++) {
      differenceInMinutes = (tstamp - snapshots[i].val().time) / 60;
      result[sensors[i]] = {current: tstamp,
                            sensor: snapshots[i].val().time,
                            diff: Math.round(differenceInMinutes * 10) / 10};
      if (differenceInMinutes < 11) {
        result[sensors[i]]['status'] = "OK";
      } else {
        result[sensors[i]]['status'] = "KO";
      }
    }
    return res.status(200).json(result);
  }).catch(error => {
    console.error('Error while getting sensors details', error.message);
    res.sendStatus(500);
  });
});

代码效果很好。所以我的问题是:如果我在传感器阵列中添加另一个房间ID,那里面不存在&#34;读数&#34;在我的数据库中,我认为我会收到错误(失败的承诺),而我只有一个巨大的超时错误,我不希望Firebase云功能出现这种超时(以避免任何不必要的成本)。

这是正常的吗?我的代码错了吗?我必须首先获得一个浅层快照&#34;读数/ room_id&#34;检查它是否存在并检查是否有孩子?

非常感谢你的帮助。

编辑:在Frank的帮助下我修复了我的代码,这是修订版:

exports.monitor = functions.https.onRequest((req, res) => {
  const tstamp = Math.floor(Date.now() / 1000);
  var sensors = ["r01", "r02", "r03", "r04", "r05"];
  var promiseArray = [];
  var result = {};
  for (var i = 0; i < sensors.length; i++) {
    console.log('Adding promise for ' + sensors[i]);
    promiseArray.push(admin.database().ref('/readings/' + sensors[i]).limitToLast(1).once("value"));
  }
  Promise.all(promiseArray).then(queryResults => {
    console.log('All promises done : ' + queryResults.length);
    res.set('Cache-Control', 'private, max-age=300');
    queryResults.forEach((snapshots, i) => {
      snapshots.forEach((snapshot) => {
        var currentData = snapshot.val();
        differenceInMinutes = (tstamp - currentData.time) / 60;
        result[sensors[i]] = {current: tstamp,
                              sensor: currentData.time,
                              diff: Math.round(differenceInMinutes * 10) / 10};
        if (differenceInMinutes < 11) {
          result[sensors[i]]['status'] = "OK";
        } else {
          result[sensors[i]]['status'] = "KO";
        }
      });
    });
    return res.status(200).json(result);
  }).catch(error => {
    console.error('Error while getting sensors details', error.message);
    res.sendStatus(500);
  });
});

1 个答案:

答案 0 :(得分:1)

child_added事件仅在存在子节点时触发。如果该位置下没有子节点(或与查询匹配),则不会触发。

为了确保您在没有孩子的情况下收到通知,您应该听取value事件:

for (var i = 0; i < sensors.length; i++) {
  console.log('Adding promise for ' + sensors[i]);
  var query = admin.database().ref('/readings/' + sensors[i]).limitToLast(1).once("value")
  promiseArray.push(query);
}

由于value事件可能与单个快照中的多个子项匹配(尽管您的查询仅请求单个子项),因此您需要遍历生成的快照的子项:

Promise.all(promiseArray).then((queryResults) => {
  console.log('All promises done : ' + queryResults.length);
  res.set('Cache-Control', 'private, max-age=300');
  queryResults.forEach((snapshots) => {
    snapshots.forEach((snapshot) => {
      differenceInMinutes = (tstamp - snapshot.val().time) / 60;
      ...