前端想要做一个定时任务?来试试这个吧
前言
在工作以及学习中,我们有时候会遇到一些定时任务的需求,比如每天定时发送邮件,定时给群或者频道发消息,定时爬取数据等等。这些其实都是比较常见的需求,但是我们又不想去部署一个专门的定时任务服务,这个时候我们就可以使用 Google App Script
实现这些需求。
Google App Script 是什么?
Google App Script
是谷歌提供的一种脚本语言,可以在谷歌的各种服务中使用,比如 Google docs
、Google sheets
、Google forms
等等。它的语法和 js
基本差不多,但是又有一些不同,比如没有 window
、document
等对象,但是有SpreadsheetApp
、DocumentApp
等对象,这些对象可以用来操作 Google docs
、Google sheets
等服务。
写代码前的准备
既然 Google App Script
可以直接操作 Google sheets
,那我们就可以直接使用 Google Sheets
来充当我们的数据库。我们在读取表格中的数据以后,再根据数据的内容来执行不同的操作。
首先我们先新建一张表格,然后在表格中填入一些数据,比如下面这样:
channel
字段表示消息要发送到的频道,hourOfDay
和 minutesOfDay
表示消息要发送的时间,message
表示消息的内容,isWorkDay 则使用了 Google Sheets
中的 NETWORKDAYS
函数来判断今天是否是工作日。而 webhook
就是我们要发送消息的 URL
。
以 slack
为例,如果想用机器人给频道发消息,我们可以在 slack
中创建一个 App
,然后在 App
中创建 一个新的Incoming Webhooks
,然后我们就可以获取到一个 Webhook URL
,我们只需要发送 POST
请求 URL
,body
中带上消息内容,就可以实现给频道发消息的功能了。
然后我们在 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
来执行我们的代码了。
这时候,就可以在 slack
中看到我们的消息了。
触发器
上面是手动执行的代码,但是我们希望代码能够自动执行,这时候就需要用到 Google App Script
的触发器了。
Tips
在设置触发器以前,有两个值得注意的地方:
- 上面的函数中,我们使用的是
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");
- 我们最好是部署我们当前的应用,
Google App Script
编辑器右上角就有部署按钮
选择脚本库,添加新版本描述,然后点击部署。就部署完成了。
触发器设置
在 App Script
中点击小时钟图标,就可以看到触发器的设置了。
选择我们要运行的函数,选择刚才部署的版本,然后设置触发器的时间,这里我们设置为每分钟执行一次,就完成了一个简单的定时任务啦。
总结
Google App Script
语法跟 JavaScript
很像,所以对于前端学习起来也很容易,提供了部署以及触发器的功能,可以帮助我们快速实现一些简单的功能。希望这篇文章能够帮助到你。
来源:juejin.cn/post/7226229808199581756