nodejs promise用法

StevieNowli 8年前

来自: 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;  };