函数返回未定义、预期的 Promise 或值,并且无法使用云函数从 firebase 数据库中删除旧数据

Function returned undefined, expected Promise or value and unable to delete old data from firebase database using cloud functions

我正在尝试删除数据库中超过 12 小时的多个节点。我正在使用 pub/sub 函数来触发此事件。我不知道我的代码是否真的循环遍历所有节点,因为我没有使用 onWriteonCreate 数据库触发器具体来说。这里是数据库的图像样本

这是pub/sub代码

 exports.deletejob = functions.pubsub.topic('Oldtask').onPublish(() => {

           deleteOldItem();
})

和 deleteOldItem 函数

function deleteOldItem(){
const CUT_OFF_TIME =  12 * 60 * 1000; // 12 Hours in milliseconds.
//var ref = admin.database().ref(`/articles/${id}`);
const ref = admin.database().ref(`/articles`);
 const updates = {};
ref.orderByChild('id').limitToLast(100).on('value', function (response) {
    var index = 0;

   response.forEach(function (child) {
    var element = child.val();

     const datetime = element.timestamp;

         const now = Date.now();

         const cutoff = now - datetime;

if (CUT_OFF_TIME < cutoff){

     updates[element.key] = null;
}

  });
//This is supposed to be the returened promise
 return ref.child(response.key).update(updates);

});

如果我做错了什么,我很想知道。 pub/sub 由已在 google 云调度程序

上设置的 JobScheduler 触发

您的代码中有几个问题给您带来麻烦。

  • 承诺的处理不正确。特别是,您的顶级函数实际上从未 return 承诺过,它只是调用了 deleteOldItems().
  • 您应该使用 once() 的承诺形式而不是使用回调调用 on() 因为在这种情况下您不想安装侦听器,您只需要一次结果,并且您想将其作为承诺链的一部分进行处理。
  • 要删除节点,您应该在对该节点的引用上调用 remove()。它还会生成一个承诺供您在此处使用。
  • 您没有正确计算 12 小时的毫秒数,您计算的是 12 分钟的毫秒数:)

这是我想出的。它使用 http 函数而不是 pubsub 函数,并为我的测试添加了一条日志语句,但是您需要的修改应该是 trivial/obvious(只需更改原型并删除 deleteOldItems 之后的响应,但是请务必确保 returning deleteOldItems()):

的结果
const functions = require('firebase-functions');
const admin = require('firebase-admin');

function deleteOldItems() {
  const CUT_OFF_TIME =  12 * 60 * 60 * 1000; // 12 Hours in milliseconds.
  const ref = admin.database().ref('/articles');
  return ref.orderByChild('id').limitToLast(100).once('value')
    .then((response) => {
      const updatePromises = [];
      const now = Date.now();

      response.forEach((child) => {
        const datetime = child.val().timestamp;
        const cutoff = now - datetime;

        console.log(`processing ${datetime} my cutoff is ${CUT_OFF_TIME} and ${cutoff}`);

        if (CUT_OFF_TIME < cutoff){
          updatePromises.push(child.ref.remove())
        }
      });

      return Promise.all(updatePromises);
    });
}

exports.doIt = functions.https.onRequest((request, response) => {
    return deleteOldItems().then(() => { return response.send('ok') });
}

虽然我没有测试过它,但我很确定它可以包含在您对云调度程序的原始函数调用中:

exports.deletejob = functions.pubsub.topic('Oldtask').onPublish(() => {
    return deleteOldItems();
})

当然,这仍然比您需要的要复杂,因为通过 id 订购并不能真正为您带来任何好处。相反,为什么不直接使用查询 return 截止时间之前最早的项目(例如,正是您要删除的项目)?我还切换到 limitToFirst 以确保 earliest 条目被丢弃,这看起来更自然并确保公平:

function deleteOldItems() {
  const cutOffTime =  Date.now() - (12 * 60 * 60 * 1000); // 12 Hours earlier in milliseconds.
  const ref = admin.database().ref('/articles');
  return ref.orderByChild('timestamp').endAt(cutOffTime).limitToFirst(100).once('value')
    .then((response) => {
      const updatePromises = [];

      response.forEach((child) => {
          updatePromises.push(child.ref.remove())
      });

      return Promise.all(updatePromises);
    });
}

如果您对多个项目执行此操作,当然,您可能希望 add an index 时间戳字段以便范围查询更有效。