后端

nodejs中vm模块的作用

月盾

vm提供了一个沙箱环境,什么叫沙箱环境?类似于一个独立的执行空间,什么时候会用到vm模块?就以我现在接触的需求来说,每个月都有运营活动,但是每次需求又不同,比如一些优惠规则不同,最后可能只需要得到一个结果,如果每次活动都去修改代码就会显得很麻烦,我们提供一个后台管理界面,或者直接在数据库里写入每次活动的不同计算规则,这些规则其实也是JavaScript代码,既然是代码就需要执行才行。这就形成了一种情况:在已有的程序中插入一段代码进行执行,这要怎么实现?如果觉得很容易插入的话,那么是不是黑客可以在你的程序中插入一段代码执行呢?这当然是不允许的,所以就需要提供一种安全环境来执行——就是沙箱了,而vm模块就是提供了这样一种执行环境。 http://www.cnblogs.com/softlover/archive/2012/10/03/2707144.html

用java的思想方式写javascript

月盾

javascript和java有相似之处也有很大区别,对于初学者来说很容易被名称迷惑,其实当初javascript就是借着java的顺风车进行推广的。

由于javascript是动态语言,java是静态语言,所以两者在编写方式上有很大区别,主要是因为javascript没有类的概念,在ES6标准发布之前要构造一个对象需要用new关键字实例化一个function或者直接使用对象字面量。不过ES6标准的发布,使得javascript也可像java一样声明类了。

在使用nodejs开发大型应用时需要到类的概念来封装一个复杂的逻辑,我们可以从现在开始逐步使用ES6开发,但是基于现有的支持环境,很多时候还得用ES5编写代码,那么这时候怎么来抽象一个类和实例化对象?

以Java的思想方式来编写JavaScript,首先是一个构造函数:

function Person(name, age){
	this.name = name;
	this.age = age;
}

这就像是Java的构造函数,可以new一个对象出来

var tom = new Person("Tom",12);

构造函数的用处是在创建对象的时候就初始化了属性的值,不用再单独赋值,不需要再像这样赋值:

var tom = new Person();

tom.name = "Tom";
tom.age = 13;

有了构造函数,还要有普通函数:

tom.sayHello = function(){

	console.log("my name is "+this.name);//my name is Tom

}

接下来是静态函数:静态方法就是由类名直接调用的的方法,不需要new一个对象

function Person(name, age){
	this.name = name;

	this.age = age;

}

Person.getAge = function(){

	console.log(this.age);

}

Person.age = 12;

Person.getAge();//类似于Java中的静态方法只能使用静态变量,所以此处也需要一个静态age

至于普通函数与静态函数有什么区别?区别就在于静态函数会一开始就加载到内存中,当然就比较占用内存了,普通函数是在new以后才被初始化,函数使用完就释放内存。

sequelizejs删除对象属性

月盾

js中有个delete操作符可以删除对象的属性,比如下面代码:

//objtest对象有个prop属性

var objtest = {

  prop: 'delete me'

};

//或者这么声明的对象

var objtest = new Array();

objtest['prop'] = 'delete me';

//删除属性'prop':

delete objtest.prop;

//或者

delete objtest['prop'];

//还可以删除任意变量

var numb = 17;

delete numb;

但是在nodejs项目中使用了sequelizejs来读取数据,如果也有想删除的属性,直接使用delete是删不掉的,比如有这样的数据结构:

var user = {
	name: '鸣人',
	age: 16,
	gender: '男',
	friends: [{
		name: '小樱',
		age: 16,
		gender: '女',
		friends: [{
			name: '井野',
			age: 16,
			gender: '女'
		}]
	},
	{
		name: '佐助',
		age: 16,
		gender: '男'
	}]
}

鸣人有小樱和佐助两个朋友,小樱有井野一个朋友,小樱的朋友也可以当做鸣人的朋友,现在想把井野也提出来并列到鸣人的朋友列表里,这样做很容易,但是既然提出来了就不需要小樱的朋友列表了,应该删掉。但是用delete user.friends[0].friends这样的方法是删不掉的。可能的是sequelize对象的属性是放在dataValues对象下面的,不能直接删除。

据我debug观察,虽然有直接属性,但是sequelize提供了getDataValue方法来获取属性值,获取到的值应该是dataValues下面的。所以,就算即使用delete删掉了直接属性还是能获取到。

但是还是有办法的,可以这样删除

user.getDataValue('friends')[0].setDataValue('friends', undefined)

就是将属性设置为undefined,查询的时候就没有小樱的friends了。

windows下使用脚本快速启动nodejs服务

月盾

每次启动node服务都要先打开cmd命令行,或者在win8下先打开文件资源管理器>文件>打开命令提示符,然后执行node命令,这样的过程真的很烦人,当然需要一个简单粗暴的方式启动了,就像用bat文件双击启动。
首先,建一个空白文件,输入以下内容:

E:  
cd E:\\NodejsWorkSpace\\app-node  
nodemon ./bin/www

就像我们平时要依次输入这些内容一样,不过还有更简单的方式:

E: && cd E:\NodejsWorkSpace\app-node && nodemon ./bin/www

使用&符号连接各个命令也可以

pm2在线监控

月盾

先来一张效果图:

](https://hopefully-img.yuedun.wang/172722906.png)

由图可以看出,监控内容有CPU,内存使用,系统bug,以及代码更新和重启服务,还有更多功能,比如bug邮件提醒功能。

使用方法很简单,几乎是一条命令搞定,首先打开https://app.keymetrics.io/#/

注册登录以后应该可以看到下图命令提示,在服务器中执行第一条命令,需要带后面的machine name

可能会失败,多试几次就可以了。然后再web页面会自动出现服务器状况。

使用nodemailer发送邮件

月盾
var nodemailer = require("nodemailer");

var transporter = nodemailer.createTransport({

	service: "gmail",

	auth: {

		user: "youname@gmail.com",

		pass: "password"

	}

});

transporter.sendMail({

	from: "youname@gmail.com",

	to: "username@qq.com",

	subject: "hello",

	text: "hello world!"

});

这是一个最基本的邮件发送程序,邮件服务商有以下:

  • “1und1”
  • “AOL”
  • “DebugMail.io”
  • “DynectEmail”
  • “FastMail”
  • “GandiMail”
  • “Gmail”
  • “Godaddy”
  • “GodaddyAsia”
  • “GodaddyEurope”
  • “hot.ee”
  • “Hotmail”
  • “iCloud”
  • “mail.ee”
  • “Mail.ru”
  • “Mailgun”
  • “Mailjet”
  • “Mandrill”
  • “Naver”
  • “Postmark”
  • “QQ”
  • “QQex”
  • “SendCloud”
  • “SendGrid”
  • “SES”
  • “Sparkpost”
  • “Yahoo”
  • “Yandex”
  • “Zoho”

sequelizejs中where条件与order排序的使用

月盾

最基本的where条件:

Post.findAll({
    where: {
        authorId: 2
    }
});
// SELECT \* FROM post WHERE authorId = 2

Post.findAll({
    where: {
        authorId: 12,
        status: active
    }
});

// SELECT \* FROM post WHERE authorId = 12 AND status = 'active';

Post.destroy({
    where: {
        status: 'inactive'
    }
});
// DELETE FROM post WHERE status = 'inactive';

Post.update({
    updatedAt: null,
},
{
    where: {
        deletedAt: {
            $ne: null
        }
    }
});

// UPDATE post SET updatedAt = null WHERE deletedAt NOT NULL;

如果涉及到or的使用,sequelize也提供了很好的解决方案

sequelize定义实体对象

月盾

sequelize定义实体对象

var sequelize = require("../utils/sequelizeDB");//连接数据库 var Sequelize = require("sequelize"); var User = sequelize.define("User", {  
user_id:{ type: Sequelize.STRING, primaryKey: true},  
name: Sequelize.STRING,  
phone: Sequelize.STRING,  
create_date: Sequelize.DATE,  
update_date: Sequelize.DATE  
}, {  
freezeTableName: true, // 默认false修改表名为复数,true不修改表名,与数据库表名同步  
tableName: "user",  
timestamps: false  
});

define函数的第一个参数’User’就是定义一个实体对象,名称不必与数据库表名一致,只是为了确定该对象没有重复 { type: Sequelize.STRING, primaryKey: true}将属性作为主键 freezeTableName禁用修改表名;默认情况下,sequelize会自动将模型名称(第一个参数定义‘User’)为复数。值为ture时不修改 tableName数据库表名 timestamps是否自动添加时间戳createAt,updateAt

node.js作为微信接口服务器

月盾

前端时间用node改写了下去年用Java练习时写的微信接口,可能是因为微信接口看的多了更加熟悉了,也可能是node开发更快速,反正不到一小时就搞定了微信token的验证,放到博客项目中,新增了一个URL请求,在微信公众平台上测试了下,没想到调试两三次就通过了,想当初用Java测试时各种问题不断。想起来可惜的是去年Java版的微信接口做的自定义菜单,自动回复等功能,由于BAE收费的缘故就废掉了。

/**  
 * Created by huopanpan on 2014/10/10.  
 */  
var crypto = require("crypto");  
/**  
 * 验证token  
 * @param req  
 * @param res  
 */  
function validateToken(req, res) {  
    var query = req.query;  
    var signature = query.signature;//微信服务器加密字符串  
    var echostr = query.echostr;//随机字符串  
    var timestamp = query["timestamp"];//时间戳  
    var nonce = query.nonce;//nonce  
    var oriArray = new Array();  
    oriArray[0] = nonce;  
    oriArray[1] = timestamp;  
    oriArray[2] = "hale";//token  
    oriArray.sort();  
    var original = oriArray[0]+oriArray[1]+oriArray[2];  
    console.log("Original Str:"+original);  
    console.log("signature:"+signature);  
    var scyptoString = sha1(original);//将三个参数拼接加密字符串,并与服务器发送的字符串对比  
    if (signature == scyptoString) {  
        res.send(echostr);  
    }  
    else {  
        res.send("Bad Token!");  
    }  
}

/**  
 * sha1加密  
 * @param str  
 * @returns {*}  
 */  
function sha1(str) {  
    var md5sum = crypto.createHash("sha1");  
    md5sum.update(str);  
    str = md5sum.digest("hex");  
    return str;  
}  
/**  
 * 重新获取access_token  
 * @type {validateToken}  
 */  
function getAccessToken(){  
    var appid = "";  
    var appsecret = "";  
    var url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=fdgf&secret=dfdsgfrf";

}  
exports.validateToken = validateToken;

Nodejs核心常用工具

月盾

内容摘自《nodejs开发指南》

util 是一个 Node.js 核心模块,提供常用函数的集合,用于弥补核心 JavaScript 的功能
过于精简的不足。
util.inherits
util.inherits(constructor, superConstructor)是一个实现对象间原型继承
的函数。JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同。JavaScript 没有
提供对象继承的语言级别特性, 而是通过原型复制来实现的, 具体细节我们在附录A中讨论,
在这里我们只介绍 util.inherits 的用法,示例如下:

var util = require("util");   
  
function Base() {   
  this.name = "base";   
  this.base = 1991;   
  
  this.sayHello = function() {   
    console.log("Hello " + this.name);   
  };   
}   
  
Base.prototype.showName = function() {   
  console.log(this.name);   
  
};   
  
function Sub() {   
  this.name = "sub";   
}   
  
util.inherits(Sub, Base);   
  
var objBase = new Base();   
objBase.showName();   
objBase.sayHello();   
console.log(objBase);   
  
var objSub = new Sub();   
objSub.showName();   
//objSub.sayHello();   
console.log(objSub);  

我们定义了一个基础对象 Base 和一个继承自 Base 的 Sub,Base 有三个在构造函数
内定义的属性和一个原型中定义的函数,通过 util.inherits 实现继承。运行结果如下:

base   
Hello base   
{ name: "base", base: 1991, sayHello: [Function] }   
sub   
{ name: "sub" } 

注意,Sub 仅仅继承了 Base 在原型中定义的函数,而构造函数内部创造的 base 属
性和 sayHello 函数都没有被 Sub 继承。同时,在原型中定义的属性不会被 console.log 作
为对象的属性输出。如果我们去掉 objSub.sayHello(); 这行的注释,将会看到: