注册

前端想要做一个定时任务?来试试这个吧

前言


在工作以及学习中,我们有时候会遇到一些定时任务的需求,比如每天定时发送邮件,定时给群或者频道发消息,定时爬取数据等等。这些其实都是比较常见的需求,但是我们又不想去部署一个专门的定时任务服务,这个时候我们就可以使用 Google App Script 实现这些需求。


Google App Script 是什么?


Google App Script 是谷歌提供的一种脚本语言,可以在谷歌的各种服务中使用,比如 Google docsGoogle sheetsGoogle forms 等等。它的语法和 js 基本差不多,但是又有一些不同,比如没有 windowdocument 等对象,但是有SpreadsheetAppDocumentApp 等对象,这些对象可以用来操作 Google docsGoogle sheets 等服务。


写代码前的准备


既然 Google App Script 可以直接操作 Google sheets,那我们就可以直接使用 Google Sheets 来充当我们的数据库。我们在读取表格中的数据以后,再根据数据的内容来执行不同的操作。


首先我们先新建一张表格,然后在表格中填入一些数据,比如下面这样:


image.png


channel 字段表示消息要发送到的频道,hourOfDayminutesOfDay 表示消息要发送的时间,message 表示消息的内容,isWorkDay 则使用了 Google Sheets 中的 NETWORKDAYS 函数来判断今天是否是工作日。而 webhook 就是我们要发送消息的 URL


slack 为例,如果想用机器人给频道发消息,我们可以在 slack 中创建一个 App,然后在 App 中创建 一个新的Incoming Webhooks,然后我们就可以获取到一个 Webhook URL,我们只需要发送 POST 请求 URLbody 中带上消息内容,就可以实现给频道发消息的功能了。


image.png


然后我们在 Google Sheets中点击 扩展程序 -> App 脚本,就会跳转到 Google App Script 的编辑器中,这个时候我们就可以开始写 js 代码了。


用法


首先,我们要先获取到 Google Sheets 中的数据。并将其转换成我们想要的格式。


const getDailyMessage = () => {
const workbook = SpreadsheetApp.getActiveSpreadsheet();
const sheet = workbook.getSheetByName(sheets.dailyMessage.sheetName);
return convertValues(sheet.getDataRange().getValues());
}

const convertValues = (values) => {
const [header, ...rows] = values;
return rows.map((row, rowIndex) => {
const result = {};
row.forEach((column, columnIndex) => {
result[header[columnIndex].trim()] = {
value: column,
position: {
row: rowIndex + 2, // skip the header row
column: columnIndex + 1,
},
};
});
return result;
});
};

有了表格中的数据以后,我们就要开始发请求了


const shouldRun = item => {
const hourOfDay = item[sheets.dailyMessage.columnNames.hourOfDay].value;
const minutesOfDay = item[sheets.dailyMessage.columnNames.minutesOfDay].value;
const currentHour = new Date().getHours();
const currentMinutes = new Date().getMinutes()
const isWorkDay = item[sheets.dailyMessage.columnNames.isWorkDay].value
if (isWorkDay && hourOfDay === currentHour && currentMinutes === minutesOfDay) {
return true
}
return false
}
// daily message
function runDailyMessage() {
const dailyMessage = getDailyMessage();
Logger.log(`${dailyMessage.length} daily message channel(s) are ready to notify...`)
const tasks = dailyMessage.filter(shouldRun).map(item => new Promise((resolve) => {
try {
const channelName =
item[sheets.dailyMessage.columnNames.channel].value;
const message = item[sheets.dailyMessage.columnNames.message].value;
const url = item[sheets.dailyMessage.columnNames.webhook].value
const options = {
method: "post",
payload: JSON.stringify({
text: message,
}),
}
const fetchResult = UrlFetchApp.fetch(url, options).getContentText();
if (fetchResult === "ok") {
afterNotify(cfg, nextMemberIndex);
}
Logger.log(`${channelName} daily message notify successfully`);
} catch (err) {
Logger.log(`${channelName} daily message throws error: `);
Logger.log(err);
} finally {
resolve()
}
}))
Promise.all(tasks)
.then(() => {
Logger.log("daily message have been executed");
})
.catch((err) => Logger.log(err));
}

写完以后,我们就可以在 Google Sheets 中点击 运行 -> runDailyMessage 来执行我们的代码了。


image.png


这时候,就可以在 slack 中看到我们的消息了。


image.png


触发器


上面是手动执行的代码,但是我们希望代码能够自动执行,这时候就需要用到 Google App Script 的触发器了。


Tips


在设置触发器以前,有两个值得注意的地方:



  1. 上面的函数中,我们使用的是 SpreadsheetApp.getActiveSpreadsheet() 获取到 Google Sheets 中的数据。但是在触发器中,使用这个 api 是无法获取到数据的,这会导致你的触发器失败。所以我们需要在触发器中使用 SpreadsheetApp.openById 来获取到 Google Sheets 中的数据。

//  use openById replace getActiveSpreadsheet when use app script trigger
const workbook = SpreadsheetApp.openById("在这里填入你 Google Sheets 的 id");


  1. 我们最好是部署我们当前的应用, Google App Script 编辑器右上角就有部署按钮

image.png


选择脚本库,添加新版本描述,然后点击部署。就部署完成了。


触发器设置


image.png


App Script 中点击小时钟图标,就可以看到触发器的设置了。


image.png


选择我们要运行的函数,选择刚才部署的版本,然后设置触发器的时间,这里我们设置为每分钟执行一次,就完成了一个简单的定时任务啦。


总结


Google App Script语法跟 JavaScript 很像,所以对于前端学习起来也很容易,提供了部署以及触发器的功能,可以帮助我们快速实现一些简单的功能。希望这篇文章能够帮助到你。


作者:xinglee
来源:juejin.cn/post/7226229808199581756

0 个评论

要回复文章请先登录注册