nodejs promise用法
来自: http://my.oschina.net/fengshuzi/blog/605957
零、关于异步
如图,是一个传统nodejs项目中比较容易看到的一种编程风格,其原因是因为nodejs底层的很多异步方法都是通过配合回调方法来实现的。理解异步我们必须掌握以下几个知识点:
1、单线程
JavaScript的引擎是单线程的,即无论是在浏览器环境还是基于JavaScript引擎的nodejs服务器环境有且仅有一段代码正被执行,JavaScript引擎不会同时执行b函数的代码和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链式写法
//返回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; };