nodejs 异步编程 vs promise用法

六月ゝ 毕业季﹏ 提交于 2020-04-07 05:57:42

零、关于异步

如图,是一个传统nodejs项目中比较容易看到的一种编程风格,其原因是因为nodejs底层的很多异步方法都是通过配合回调方法来实现的。理解异步我们必须掌握以下几个知识点:

1、单线程

JavaScript的引擎是单线程的,即无论是在浏览器环境还是基于JavaScript引擎的nodejs服务器环境有且仅有一段代码正被执行,JavaScript引擎不会同时执行a函数的代码和b函数的代码。

2、JavaScript轮询机制(主线程 VS Event Loop线程)

轮询(event loop)简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")。

就是说执行我们程序员写的代码的是主线程,当主线程遇到io操作的时候,主线程就通知Event Loop线程去执行相应的I/O程序,自己则继续执行其他代码,当Event Loop线程把io任务完成后会主动告诉主线程我已经执行完了,主线程收到通知后会调用事先准备好的回调函数,完成整个任务。

基于以上原因早期的nodejs 代码会存在大量的callback函数嵌套,这些callback正是为主线程在收到Event Loop线程完成io操作后准备的回调函数。

3、如何与Event Loop线程打交道?

作为一个习惯了java多线程的程序员,这个问题其实困扰了我很久,淡实际上我们其实并不需要直接与Event Loop线程打交道,最起码短时间内你不必自己封装跟Event Loop线程打交道的异步方法。

大部分异步方法其实都已经封装好了,比如JavaScript ajax请求,或者http请求的http框架,或者数据库操作的orm框架等

4、callback引发的问题

由上图展开联想,当存在多层调用的时候,callback将会深层嵌套,给代码可读性和维护性造成困扰。

一、promise简介

promise是一种规范,一种解决callcack深层嵌套的方案,一种带有then方法支持链式操作的框架.

二、promise 用法

//返回json格式字符串
exports.get = function (url, data) {
	var deferred = Q.defer();
	data = data || {};
	http.get('http://' + url.host + ':' + url.port + url.path + '?' + querystring.stringify(data), function (res) {
		var result = '';
		res.setEncoding('utf8');
		res.on('data', function (chunk) {
			result += chunk;
		});
		res.on('end', function () {
			var statusCode = res.statusCode;
			if (statusCode === 200) {
				result = result ? JSON.parse(result) : false;
				deferred.resolve(result);
			} else {
				deferred.reject("get error statusCode: " + statusCode);
			}
			
		});
	}).on('error', function (e) {
		console.log("调用api 失败:" + e);
		deferred.reject('get Error:' + e.message);
	});
	
	return deferred.promise;
};



三、promise链式写法

通过链式写法调用上面的get方法


/**
 * 进入商品详情页面
 */
exports.detail = function (req, res) {
	console.log("enter method product.detail");
	var query = req.query;
	var promise = productService.getProductById(query.id);
	var product = {};
	promise.then(function (result) {
		product = result;
		var query = {
			"productListType": "BOSS_BRAND_PRODUCT_LIST",
			"sort": "realSupportNum-desc"
		};
		return productService.getProductListById(result.brandId + "-" + result.id, query);
	}).then(function (result) {
		console.log(result);
		console.log(product);
		res.render("product/product", {
			product: product,
			brandProducts: result.datas
		});
	}).catch(function (e) {
		product.status = 0;
		console.log("获取商品详情失败" + e);
		res.json("出错了");
	});
};






易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!