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中參數如有"[]"沒必要加引號。
相關文章
相關標籤/搜索