定时任务:node-schedule
1、指定一个具体时间执行任务
1var schedule = require('node-schedule');
2var date = new Date(2016, 10, 11, 23, 59, 59);
3//月份从0开始算
4var j = schedule.scheduleJob(date, function(){
5 console.log('这不应该是个虐狗的时节!');
6});
2、每天指定一个时间将到期的邮件发送
1var registerTask=function(hour,minute,taskname){
2 return new Promise(function(resolve,reject){
3 var rule = new schedule.RecurrenceRule();
4 //每天这个时刻定时执行任务
5 rule.dayOfWeek = [0, new schedule.Range(1, 6)];
6 rule.hour = hour;
7 rule.minute = minute;
8 var j = schedule.scheduleJob(rule, function(){
9 console.log("开始发送:"+taskname);
10 resolve();
11 });
12 });
13}
3、时间的设置取决于rule的配置
(1)、每秒:rule.second=[0,1,2,...59];
(2)、每分钟:rule.minute=[0,1,2,...59];
(3)、每小时:rule.hour=[0,1,2,...23];
(4)、每周几:rule.dayOfWeek=[0,1,...7];
(5)、每月几号:rule.dayOfMonth=[1,2,3,...31];
(6)、每月:rule.month=[1,2,...12];
4、到期重新赋值
1var schedule = require('node-schedule');
2var date = new Date(2016, 10, 11, 23, 59, 59);
3var x = 'old value!';
4var j = schedule.scheduleJob(date, function(y){
5 console.log(y);
6}.bind(null,x));
7x = 'new value';
不出意外的话,定时任务就可以跑起来了;
如果你也在使用pm2的话,想必会根据CPU的核数开启多个进程(比如:pm2 start ./app.js -i 4),那么恭喜你,你将碰到一个很有意思的问题:你的定时任务会重复4次发送同一个邮件;
听人说,定时任务最好独立出去单独运行,这个独立站点只执行定时任务,不使用pm2启动,想了想挺有道理的;好笑的是,我独立一个站点不开启多个进程依然会多次发送邮件;因为我使用的是mongoose,这个独立站点里require不到主站里的models,于是我在主站里新增了两个GET请求,发送邮件的站点定时去请求主站的待发送邮件的数据,发送完毕后回调里再请求去更新发送状态,最后的结果是仍然会重复发送;思来想去,然后我就此卡住了!
时间过去了大概不到一个月,突然有一天,我发现作为一个前端,要想学好Node,数据库才是最大的短板啊!再看了下mongodb,果然,不用mongoose,不require主站的models也能在这两个不同的站点访问同一个数据库;于是之前卡住的问题就迎刃而解了;————————跳到邮件发送!
邮件发送:nodemailer
这个问题挺多的,但是稳住了就不会有什么问题了;一般就密码的问题,重复发送会被认为是垃圾邮件;以下为完整版,目前为止能顺利的用,倾情推荐:
1var emailManage = {};
2var nodemailer = require("nodemailer");
3var smtpTransport = require('nodemailer-smtp-transport');
4
5emailManage.send = function (_data,geter,title,htmlbody) {
6 return new Promise(function(resolve,reject){
7 var transport = nodemailer.createTransport(smtpTransport({
8 host: "smtp.qq.com", // 主机
9 port: 465, // SMTP 端口
10 auth: {
11 user: "[email protected]", // 账号
12 pass: "去邮箱设置后获取,不是QQ密码"
13 }
14 }));
15 transport.sendMail({
16 from: "[email protected]", // 发件地址
17 to: geter, // 收件列表
18 subject: title, // 标题
19 html: htmlbody
20 }, function(error, response) {
21 error&&reject(error);
22 resolve(_data);
23 //transport.close(); // 如果没用,关闭连接池
24 });
25 });
26}
27module.exports=emailManage;
跳回定时任务。独立出来的站点是可以连接到主站的数据库的,不用想着去require主站的models了;至此,慢邮版块的定时邮件发送任务就完成了;
1var mongodb = require('mongodb');
2var server = new mongodb.Server('localhost', 27017, {auto_reconnect:true});
3var db = new mongodb.Db('dbname', server, {safe:true});
4var dbColl=null;
5var openDB=function(){
6 return new Promise(function(resolve,reject){
7 db.open(function(err,dab){
8 err&&reject(err);
9 resolve(dab);
10 });
11 });
12}
13var getCollection=function(db,coll){
14 return new Promise(function(resolve,reject){
15 db.collection(coll,{safe:true},function(err,collection){
16 err&&reject(err);
17 dbColl=collection;
18 resolve(collection);
19 });
20 });
21}
22var getFus=function(collection){
23 return new Promise(function(resolve,reject){
24 var dateDayStamp = new Date(new Date().getFullYear()+'-'+(new Date().getMonth()+1)+'-'+new Date().getDate()).getTime()+'';
25 collection.find({timeStamp:{$lte:dateDayStamp},sended:0}).toArray(function(err,fus){
26 err&&reject(err);
27 resolve(fus);
28 });
29 });
30}
31var fusPromises=function(fus){
32 if (fus.length) {
33 return fus.map(function(f){
34 return emailManage.send(
35 {
36 fid:f.fid,
37 getter:f.getter,
38 sender:f.sender,
39 emailto:f.emailto
40 },
41 f.emailto,
42 '你好,这是一封'+f.timeName+'前'+f.sender+'发给您的-时光慢递',
43 decodeURIComponent(f.body)
44 );
45 });
46 }
47 return [Promise.reject('need not to send ...')];
48 //直接跳到catch
49}
50var updateFus=function(ifs){
51 var updateOne=function(f){
52 return new Promise(function(resolve,reject){
53 dbColl.update({fid:f.fid},{$set:{sended:1}},{},function(err){
54 err&&reject(err);
55 console.log('sended to '+f.emailto);
56 console.log('+---------------------------------+');
57 resolve();
58 });
59 });
60 }
61 return ifs.map(function(f){
62 return updateOne(f);
63 });
64}
65
66registerTask(22,45,'慢邮')
67.then(function(){
68 return openDB();
69})
70.then(function(dba){
71 return getCollection(dba,'futures');
72})
73.then(function(collection){
74 return getFus(collection);
75})
76.then(function(fus){
77 return Promise.all(fusPromises(fus));
78})
79.then(function(ifs){
80 return Promise.all(updateFus(ifs));
81})
82.then(function(){
83 console.log('all sended');
84})
85.catch(function(err){
86 console.log(err);
87});
好了,先给Promise点个赞!