【问题标题】:Firebase clearTimeout not stop the setTimeoutFirebase clearTimeout 不会停止 setTimeout
【发布时间】:2018-06-21 01:41:27
【问题描述】:

如何在“Firebase 云函数”上的 onWrite 事件开始之前停止 setTimeout 函数?我尝试使用 setTimeout,但 clearTimeout 不会停止 setTimeout。

P.S.:我已经将 Firebase 面板的脚本超时时间从 60 秒(默认)提高到 360 秒。

var timeOutOnline = {};
exports.online = functions.database.ref('/server/{serverId}/online/time').onWrite(event => {
    const serverId = event.params.serverId;
    var time = event.data.val();
    var lastDateOnline = new Date( time * 1000);
    var dateString = lastDateOnline.toGMTString();

    clearTimeout(timeOutOnline[serverId]);

    refGet = db.ref('/server/'+serverId+'/online/');
    refGet.once('value').then(function(snapshot) {
            var onlineSnap = snapshot.val();
            if (onlineSnap && onlineSnap.alarm == true) {
                    sendMail(serverId,false, 'not responding' , 'Server '+ serverId + ' not responding from '+dateString);
                    setAlarmStatus(serverId,false);
            } else {
                    timeOutOnline[serverId] = setTimeout(function() {
                            sendMail(serverId,true, 'not responding' , 'Server '+ serverId + ' not responding from '+dateString);
                            setAlarmStatus(serverId,true);
                    }, 21000);
            }

    });
    return true;
});

更新: 现在我使用promise,但是clearTimeout 仍然不起作用,没有清除setTimeout 函数。我做错了什么?

var timeOutOnline = {};
exports.online = functions.database.ref('/server/{serverId}/online/time').onWrite(event => {
    const serverId = event.params.serverId;
    var time = event.data.val();
    var lastDateOnline = new Date( time * 1000);
    var dateString = lastDateOnline.toGMTString();

    console.log(v);

    if(!timeOutOnline[serverId]) {
            timeOutOnline[serverId] = [];
    } else {
            timeOutOnline[serverId].length;
            for (var i = 0; i < timeOutOnline[serverId].length; i++) {
                    if (timeOutOnline[serverId][i]) {
                            timeOutOnline[serverId][i].cancel();
                            timeOutOnline[serverId][i] = null;
                    }
            }
    }

    timeOutOnline[serverId] = timeOutOnline[serverId].filter(n => n);

    refGet = db.ref('/server/'+serverId+'/online/');
    refGet.once('value').then(function(snapshot) {
            var onlineSnap = snapshot.val();
            if (onlineSnap && onlineSnap.alarm == true) {
                    sendMail(serverId,false, 'not responding' , 'Server '+ serverId + ' not responding from '+dateString);
                    setAlarmStatus(serverId,false);
            } else {
                    timeOutOnline[serverId].push(waitForServer(210000));
                    var index = timeOutOnline[serverId].length - 1;

                    return timeOutOnline[serverId][index].promise.then(function(i) {
                            console.log('Server '+ serverId + ' not responding from '+dateString);
                            sendMail(serverId,true, 'not responding' , 'Server '+ serverId + ' not responding from '+dateString);
                            setAlarmStatus(serverId,true);

                    });
            }

    });

    return true;
});


function waitForServer(ms) {
    var timeout, promise;

    promise = new Promise(function(resolve, reject) {
            timeout = setTimeout(function() {
                    resolve('timeout done');
            }, ms);
    });

    return {
            promise:promise,
            cancel:function(){
                    console.log('cancel timeout: '+timeout);
                    clearTimeout(timeout);
            }
    };
}

【问题讨论】:

  • 这应该可以正常工作,假设超时存在于它被停止的时间,并且 timeOutOnline 中的那个键没有被覆盖(考虑到你的代码,这不一定是不可能的,因为有延迟在清除任何现有的和开始新的之间)
  • Firebase 可以清理 timeOutOnline 数组吗?
  • 哈哈,不,那会很神奇

标签: javascript node.js firebase google-cloud-functions


【解决方案1】:

这个函数有很多问题。

首先,我不清楚为什么要在此函数中使用 setTimeout()。事实上,使用 Cloud Functions 的 setTimeout() 几乎没有有效的用例。函数应该尽可能快地执行,而 setTimeout 只会给您的处理带来额外的成本。 Cloud Functions 无法让您运行在函数调用之后仍然存在的“后台工作”——这不是它的工作方式。

其次,您在这里执行异步工作,但您不是 returning a promise 来指示该工作何时完成。如果您在工作完成时没有返回已解决的承诺,那么您的函数很可能会出现奇怪的问题,包括工作未按预期完成。

【讨论】:

  • 我知道在 Firebase 中使用超时可能会很昂贵或错误,但应用程序很小且不公开,我仅用于监控我们的服务器。我尝试使用承诺,但我可能错了。我已经更新了原帖。
  • 您仍然没有从函数返回承诺。您正在返回true。请解释为什么你需要使用 setTimeout 以及你期望这个函数做什么。
  • 我的所有服务器每隔几分钟就会在 Firebase 数据库上写入一次,每次一台服务器写入 db 时,脚本清理活动超时。如果超时功能将运行,服务器可能处于离线状态并向我发送通知。
  • Cloud Functions 无法满足您的需求。如果您需要监控您的服务器,您应该使用其他一些专用的监控工具。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 2021-02-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多