目录
介绍
解释代码
解析函数
特别案例
AWS设置
AWS Lambda
AWS API网关
AWS Amplify
- 下载 index.html - 884 B
- 下载 index.js.txt - 3.1 KB
这个项目对我来说有点锻炼。我最近开始在AWS中学习初学者的东西,所以我想通过创建一个简单的API来测试Lambda函数。本文介绍了如何使用AWS Lambda(一个使用AWS Amplify的简单网站)创建API函数,并使用AWS API Gateway连接这两者。
lambda函数本身是一个用Node.js编写的cron表达式解析器。它将Cron表达式作为参数,并在该cron表达式下一次触发事件时计算并返回。
解释代码通过API事件接收的表达式首先针对两个表达式进行测试,如果匹配,则将其拆分为要解析的数组。
var matches_POSIX = regex_POSIX.exec(testexp);
var matches_EXT = regex_EXT.exec(testexp);
var arr = [];
if(matches_POSIX === null && matches_EXT === null) {
console.log("Expression does not match!!!");
return null;
}
else if(matches_POSIX !== null) {
console.log("Expression is POSIX");
arr.push("*");
matches_POSIX.forEach((m, i) => i != 0 ? arr.push(m) : null);
arr.push("*");
if(arr[3] != "?" && arr[5] == "*") arr[5] = "?";
if(arr[5] != "?" && arr[3] == "*") arr[3] = "?";
}
else {
console.log("Expression is EXTENDED");
matches_EXT.forEach((m, i) => i != 0 ? arr.push(m) : null);
}
主要功能是getNextTime。它将遍历数组的所有元素并使用适当的参数调用resolve函数。它还将测试已解决的错误值,这基本上是返回数组的第一个元素中的值-1。
解析顺序为:年-月-星期-日-时-分-秒。这种倒推方法的原因是因为,例如,要知道一个月有多少天,我们需要知道它是哪一年,要知道某个日期的哪个工作日,我们需要知道月份和年份等。
稍后我们在确定下一个触发cron事件的时间时也会使用这种方法,因为我们希望通过获取最接近的未来日期来缩小时间窗口;这将在后面的文本中更彻底地解释。
解析函数根据正在求值的cron表达式的哪一部分(通过第二个参数传递),这个函数被分成几个部分;参数值的含义在上面的注释中解释了:
switch(i) {
// year
case 6:
if(m === "*") return Array.apply(null, Array(10)).map(function(e, i)
{ return ts.getFullYear() + i; }); // current and next 9 years
if(!m.includes("-") && !m.includes(","))
return [parseInt(m, 10)]; // single value
return resolveList(m, i); // list of years
// month
case 4:
if(m === "*") return Array.apply(null,
Array(12)).map(function(e, i) { return i; }); // return all months
if(!m.includes("-") && !m.includes(",") && !isNaN(parseInt(m, 10)))
return [parseInt(m, 10)-1]; // single value numeric
if(isNaN(parseInt(m, 10)) && month2num(m) != -1)
return [month2num(m)-1]; // single value string
return resolveList(m, i).map(function(e,i)
{ return (e > 0 ? e-1 : e) }); // list of months
// day of month
case 3:
if(m === "?") return undefined; // empty - use dw instead
if(m === "*") return Array.apply(null, Array
(new Date(yyyy, mm+1, 0).getDate())).map(function(e, i)
{ return i + 1; }); // return all days
if(m.replace(/L|W/g,"").length != m.length)
return null; // last (week)day of month - skip,
// resolve outside this function
if(!m.includes("-") && !m.includes(","))
return [parseInt(m, 10)]; // single value
return resolveList(m, i); // list of days
// day of week
case 5:
if(m.replace(/L|#/g,"").length != m.length)
return null; // just ignore special cases,
// to be resolved outside this function
if(m === "?") return undefined; // empty - use dd instead
if(m === "*") return Array.apply(null, Array(7)).map
(function(e, i) { return i; }); // return all days
if(!m.includes("-") && !m.includes(","))
return [parseInt(m, 10)]; // single value numeric
if(isNaN(parseInt(m, 10)) && day2num(m) != -1)
return [day2num(m)]; // single value string
return resolveList(m, i); // list of days
// hour
case 2:
if(m === "*") return Array.apply(null,
Array(24)).map(function(e, i) { return i; }); // return all hours
if(!m.includes("-") && !m.includes(",") && !m.includes("/"))
return [parseInt(m, 10)]; // single value
return resolveList(m, i); // list of hours
// min / sec
case 1: case 0:
if(m === "*") return Array.apply(null, Array(60)).map(function(e, i)
{ return i; }); // return all min/sec
if(!m.includes("-") && !m.includes(",") && !m.includes("/"))
return [parseInt(m, 10 )]; // single value
return resolveList(m, i); // list of min/sec
}
该resolve函数尝试为cron的每个部分返回一个包含所有可能值的数组(年份除外;因为年份是无限的,该函数最多将返回未来10年)。
如果提供了星号(*),则表示所有的值都是可能的,因此首先使用Array.apply函数创建一个数组,以null元素为初始值,然后使用map函数设置元素,例如12个月:
if(m === "*") return Array.apply(null, Array(12)).map(function(e, i)
{ return i; }); // return all months
可能的结果要么是所有值(*),只有一个值,要么是用逗号分隔的列表或范围表示的值列表——这在名为resolveList的单独函数中解析:
function resolveList(m, i) {
var retValue = [];
var msplit;
var k;
var limit;
if(m.includes("-")) { // all in between
msplit = m.split("-").map(function(e) {
if(i == 4) e = month2num(e);
if(i == 5) e = day2num(e);
return parseInt(e, 10);
});
if (msplit[0] < msplit[1]) {
for(k = msplit[0]; k { // remove duplicates
//console.log("currentValue=" + k + " ; retValue=" + retValue.toString());
if(!retValue.includes(k)) retValue.push(k);
});
return retValue.sort(); // sort
//m.split(",").forEach(k => retValue.push(parseInt(k)));
}
else if(m.includes("/")) {
msplit = m.split("/");
if(msplit[0] == "*") msplit[0] = "0";
msplit = msplit.map(function(e) {
return parseInt(e, 10);
});
if(i 0; i--)
{ // start from end of month and look for last specified weekday in that month
if(parseInt(exp.substring(0,1),10) == new Date(yyyy, mm, i).getDay())
return i;
}
if(exp.includes("#")) {
var n = 0;
for(i = 1; i {
// instantiate a headers object
var myHeaders = new Headers();
// add content type header to object
myHeaders.append("Content-Type", "application/json");
// using built in JSON utility package turn object
// to string and store in a variable
var raw = JSON.stringify({"key1":key1});
// create a JSON object with parameters for API call and store in a variable
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
// make API call with parameters and use promises to get response
fetch("YOUR API INVOKE URL HERE", requestOptions)
.then(response => response.text())
.then(result => document.getElementById('result').innerHTML =
result/*alert(JSON.parse(result).body)*/)
.catch(error => document.getElementById('result').innerHTML =
error/*console.log('error', error)*/);
}
Enter Cron expression here
Submit
Result:
将“YOUR API INVOKE URL HERE”替换为您在上一步中保存的URL。
保存“index.html”,然后ZIP(压缩)它(您可以随意命名ZIP)。
现在返回AWS控制台(您的Amplify应用程序),然后单击“选择文件”,然后打开包含“index.html”的zip 。保存并部署。
就是这样。现在您可以使用“Domain”下的URL打开您的HTML网页。输入一个cron表达式来测试它并单击Submit,您的API应该在Result下返回一个值。