如何为同时触发的函数添加延迟?解决Telegram机器人429报错
解决Telegram机器人429限流问题:让三个函数间隔5分钟运行
问题根源
你碰到的429 Too Many Requests是Telegram API的防 spam机制,三个发送消息的函数被同时调用,请求频率超标触发了限制。要解决这个问题,必须让三个函数错开5分钟依次执行,不能同时运行。
推荐方案:用独立触发器分别调度
这种方法借助Google Apps Script的时间触发器,给每个函数单独设置执行时间,既不会触发脚本超时限制,稳定性也更高。
修改后的代码如下:
// 主触发函数:负责安排当天三个函数的执行,以及第二天的自动触发 function function_Triggered() { // 先清除旧触发器,避免重复运行 deleteAllTriggers(); // 分别给三个函数设置执行时间:8点、8点5分、8点10分 scheduleFunctionAtTime(FunctionOne, 8, 0); scheduleFunctionAtTime(FunctionTwo, 8, 5); scheduleFunctionAtTime(FunctionThree, 8, 10); // 安排第二天的主触发,保证每天自动执行 scheduleNextDayMainTrigger(); } // 辅助函数:为指定函数设置特定时间的触发器 function scheduleFunctionAtTime(targetFunction, hours, minutes) { var now = new Date(); var scheduledDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes); // 如果当天目标时间已过,自动安排到第二天 if (scheduledDate < now) { scheduledDate.setDate(scheduledDate.getDate() + 1); } var delayMs = scheduledDate.getTime() - now.getTime(); ScriptApp.newTrigger(targetFunction.name) .timeBased() .after(delayMs) .create(); } // 设置第二天的主触发,确保每日自动执行 function scheduleNextDayMainTrigger() { var now = new Date(); var nextDay = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 8, 0); var delayMs = nextDay.getTime() - now.getTime(); ScriptApp.newTrigger("function_Triggered") .timeBased() .after(delayMs) .create(); } // 清除所有相关触发器,避免堆积 function deleteAllTriggers() { var triggers = ScriptApp.getProjectTriggers(); var targetFunctions = ["function_Triggered", "FunctionOne", "FunctionTwo", "FunctionThree"]; for (var i = 0; i < triggers.length; i++) { if (targetFunctions.includes(triggers[i].getHandlerFunction())) { ScriptApp.deleteTrigger(triggers[i]); } } }
代码说明
function_Triggered作为入口,先清理旧触发器,再为三个发送函数分别设置执行时间,最后安排次日的自动触发任务。scheduleFunctionAtTime会自动计算当前时间到目标时间的差值,创建延迟触发器;如果当天目标时间已过,直接顺延至次日。deleteAllTriggers会清理所有相关触发器,防止重复创建导致消息重复发送。
备选方案:单个脚本内添加延迟(不推荐)
如果一定要在同一个触发函数内完成三个函数的执行,可以使用Utilities.sleep()添加延迟,但要注意Google Apps Script单脚本最长执行时间约为6分钟,三个函数间隔5分钟的总耗时会超过限制,大概率会被中断,仅适合函数本身耗时极短的场景。
示例代码:
function function_Triggered() { try { FunctionOne(); // 延迟5分钟(300000毫秒) Utilities.sleep(300000); FunctionTwo(); Utilities.sleep(300000); FunctionThree(); } catch (e) { console.log("执行出错:" + e.message); } deleteTriggers(); scheduledTrigger(8, 0); } // 保留原有调度和清理触发器函数,注意参数格式改为(8,0)而非8.00 function scheduledTrigger(hours, minutes){ var now = new Date(); var year = now.getFullYear(); var month = now.getMonth(); var day = now.getDate(); var pars = [year, month, day, hours, minutes]; var scheduled_D = new Date(...pars); // 如果当天8点已过,安排到第二天 if (scheduled_D < now) { scheduled_D.setDate(scheduled_D.getDate() + 1); } var delayMs = scheduled_D.getTime() - now.getTime(); ScriptApp.newTrigger("function_Triggered") .timeBased() .after(delayMs) .create() } function deleteTriggers(){ var triggers = ScriptApp.getProjectTriggers(); for (var i = 0; i<triggers.length; i++) { if (triggers[i].getHandlerFunction() === "function_Triggered") { ScriptApp.deleteTrigger(triggers[i]); } } }
额外优化建议
无论采用哪种方案,建议在发送消息的函数中添加429错误的重试逻辑,根据Telegram返回的retry_after值自动等待后重试,示例:
function sendTelegramMessage(chatId, text) { var url = "https://api.telegram.org/bot<你的机器人令牌>/sendMessage"; var options = { method: "post", payload: { chat_id: chatId, text: text }, muteHttpExceptions: true // 允许获取完整错误响应 }; var response = UrlFetchApp.fetch(url, options); var result = JSON.parse(response.getContentText()); if (!result.ok) { if (result.error_code === 429) { var retryAfter = result.parameters.retry_after || 30; console.log("触发限流,等待" + retryAfter + "秒后重试"); Utilities.sleep(retryAfter * 1000); return sendTelegramMessage(chatId, text); // 递归重试 } else { throw new Error("发送失败:" + result.description); } } return result; }
内容的提问来源于stack exchange,提问作者Angely Fransiska
相关产品推荐
相关产品推荐

