nodejs的promise与q

什么是promise

参见维基百科上的定义和Promises/A+javascript

由来

  1. 解决nodejs的回调金字塔,减小代码的缩进,下降代码理解的负担。
  2. 文章[译] 深刻理解 Promise 五部曲中又阐述了另一种角度。

promise的一种实现:q

q参见npm上的官方文档 把文档示例看了一遍一通折腾以后,想说爱你不容易。一不当心就容易掉坑里。 贴一下使用q重构先后的代码对比:java

//重构前
//用户注册
function create_user(req, rep, next) {
	var body_kv = querystring.parse(req.body);
	var mobile = body_kv.mobile
		, passwd = body_kv.passwd
		, mobile_ver_code = body_kv.mobile_ver_code;

	console.log(mobile, passwd, mobile);

	//校验手机验证码
	r_cli.get(mobile, function(err, res){
		if (err) throw err;
		if(res !== mobile_ver_code){
			rep.send({code: -2, message: "手机验证码错误"});
			return;
		}
		//若手机号码不存在,新增用户信息。
		my_cli.query('select 1 from user_info where mobile = ?', [mobile], function(err, rows){
			if (err) throw err;
			if (rows.length !== 0) {
				rep.send({code: 1, message: "用户已存在"});
				return; 
			}
			my_cli.query('insert into user_info (mobile, passwd, create_time) values ( ? , ?, now())', [mobile, passwd], function(err, result){
				if (err) throw err;
				//增长token与userid的关联
				var userid = result.insertId;
				var token = uuid.v4();
				r_cli.set(token, userid, function(err, result){
					if (err) throw err;
					rep.send({code: 0, message: "注册成功", token: token});
				});
				r_cli.expire(token, token_expire_time);
			});
		});
	});
}
//重构后
//生成token并缓存
function cache_token(userid){
	var token = uuid.v4();
	return Q.npost(r_cli, 'set', [token, userid])
			.then(Q.npost(r_cli, 'expire', [token, token_expire_time]))
			.then(function(){
				return Q(token);
			});
}

//用户注册
function create_user(req, rep, next) {
	var body_kv = querystring.parse(req.body);
	var mobile = body_kv.mobile
		, passwd = body_kv.passwd
		, mobile_ver_code = body_kv.mobile_ver_code;

	var ret = {};
	Q.npost(r_cli, 'get', [mobile])
	.then(function(res){
		if (res !== mobile_ver_code)
			return Q.reject({code: -2, message: "手机验证码错误"});
		return Q(mobile);
	})
	.then(function(mobile){
		return Q.npost(my_cli, 'query', ['select 1 from user_info where mobile = ?', [mobile]])
				.then(function(rows){
					if (rows[0].length !== 0) 
						return Q.reject({code: 1, message: "用户已存在"});
					return Q(rows);
				});
	})
	.then(function(rows){
		return Q.npost(my_cli, 'query', ['insert into user_info (mobile, passwd, create_time) values ( ? , ?, now())', [mobile, passwd]])
				.then(function(result){
					return Q(result[0].insertId);
				});
	})
	.then(cache_token)
	.done(function(token){
		rep.send({code: 0, message: "注册成功", token: token});
	},function(err){
		console.log('err is : ' + util.inspect(err));
		rep.send(err);
	});
}

感受代码量不减反增。node

须要注意的几个地方

  1. then关键字调用的是fulfilled函数,若是参数省略就是上面promise实例返回的值。
  2. mysql返回的result、field在q.defer.promise中为一个数组res,result要用res[0]取。
  3. Q.npost中参数如有"[]"没必要加引号。
相关文章
相关标签/搜索