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; };