2-5 开发通知功能
class QueryTicket{ constructor({ data, phoneNumber, cookie, day }) { //constructor代码... } //初始化 async init(){ let ticketList = await this.handleQueryTicket() //如果有余票 if (ticketList.length) { //把余票传入购票逻辑方法,返回短信通知所需要的数据 let resParse = await this.handleBuyTicket(ticketList) //执行通知逻辑 this.handleInfoUser(resParse) } } //查询余票的逻辑 async handleQueryTicket(){ // 查询余票代码... } //调用查询余票接口 requestTicket(){ //调用查询余票接口代码... } //购票相关逻辑 async handleBuyTicket(ticketList){ //购票代码... } //调用购票接口 requestOrder(obj){ //购票接口请求代码... } //通知用户的逻辑 async handleInfoUser(parseData){ //获取上一步购票的response数据和我们拼接的数据 let { returnCode, returnData: { main: { lineName, tradePrice } }, queryParam: { dateStr, tickAmount, startTime, station } } = parseData //如果购票成功,则返回500 if (returnCode === "500") { let res = await this.sendMsg({ dateStr, //日期 tickAmount: tickAmount.slice(0, -1), //总张数 station, //站点 lineName, //巴士名称/路线名称 tradePrice,//总价 startTime,//出发时间 phoneNumber: this.phoneNumber,//手机号 }) //如果发信成功,则不再进行抢票操作 if (res.result === 0 && res.errmsg === "OK") { this.setStop(true) } else { //失败不做任何操作 console.log(res.errmsg) } } else { //失败不做任何操作 console.log(resParse['returnInfo']) } } //发短信接口 sendMSg(){ let { dateStr, tickAmount, station, lineName, phoneNumber, startTime, tradePrice } = obj var appid = 140034324; // SDK AppID 以1400开头 // 短信应用 SDK AppKey var appkey = "asdfdsvajwienin23493nadsnzxc"; // 短信模板 ID,需要在短信控制台中申请 var templateId = 7839; // NOTE: 这里的模板ID`7839`只是示例,真实的模板 ID 需要在短信控制台中申请 // 签名 var smsSign = "测试短信"; // NOTE: 签名参数使用的是`签名内容`,而不是`签名ID`。这里的签名"腾讯云"只是示例,真实的签名需要在短信控制台申请 // 实例化 QcloudSms var qcloudsms = QcloudSms(appid, appkey); var ssender = qcloudsms.SmsSingleSender(); // 这里的params就是短信里面可以自定义的内容,也就是填入{1}{2}..的内容 var params = [dateStr, station, lineName, startTime, tickAmount, tradePrice]; //用promise来封装下异步操作 return new Promise((resolve, reject) => { ssender.sendWithParam(86, phoneNumber, templateId, params, smsSign, "", "", function (err, res, resData) { if (err) { reject(err) } else { resolve(resData) } }); }) } }
如果发信成功,返回 result:0
到这里,大部分需求已经完成了,还剩下一个定时任务
2-6 定时任务
也声明一个类,这里我们用到的是 schedule
// 定时任务 class SetInter { constructor({ timer, fn }) { this.timer = timer // 每几秒执行 this.fn = fn //执行的回调 this.rule = new schedule.RecurrenceRule(); //实例化一个对象 this.rule.second = this.setRule() // 调用原型方法,schedule的语法而已 this.init() } setRule() { let rule = []; let i = 1; while (i < 60) { rule.push(i) i += this.timer } return rule //假设传入的timer为5,则表示定时任务每5秒执行一次 // [1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56] } init() { schedule.scheduleJob(this.rule, () => { this.fn() // 定时调用传入的回调方法 }); } }
2-7 多个用户抢票
假设我们有两个用户要抢票,所以定义两个obj,实例化下 QueryTicket 类
data: { //用户1 lineId: 111130, vehTime: 0722, startTime: 0751, onStationId: 564492, offStationId: 17990, onStationName: '宝安交通运输局③', offStationName: "深港产学研基地", tradePrice: 0, saleDates: '', beginDate: '', }, phoneNumber: 123123123, cookie: 'JSESSIONID=TESTCOOKIE', day: "17" } var obj2 = { //用户2 data: { lineId: 134423, vehTime: 1820, startTime: 1855, onStationId: 4322, offStationId: 53231, onStationName: '百度国际大厦', offStationName: "裕安路口", tradePrice: 0, saleDates: '', beginDate: '', }, phoneNumber: 175932123124, cookie: 'JSESSIONID=TESTCOOKIE', day: "" } var ticket = new QueryTicket(obj) //用户1 var ticket2 = new QueryTicket(obj2) //用户2 new SetInter({ timer: 1, //每秒执行一次,建议5秒,不然怕被ip拉黑,我这里只是为了方便下面截图 fn: function () { [ticket,ticket2].map(item => { //同时进行两个用户的抢票 if (!item.getStop()) { //调用实例的原型方法,判断是否停止抢票,如果没有则继续抢 item.init() } else { // 如果抢到票了,则不继续抢票 console.log('stop') } }) } })
node index.js 运行下,跑起来了
如果他抢到票的话,我就会收到短信通知:
打开手机,看下订单信息
搞定,收工
写在最后
其实可以在此基础上还能添加更多功能,比如直接抓取登录接口获取cookie,指定路线抢票,还有错误处理啊啥的
因为这个只是我个人使用,所以只有这点功能就足够了。
如果想把它做成一个完整的项目,建议使用ts加持 ,关于ts我推荐阅读这篇JD前端写的文章
希望各位能有所收获
总结