nodejs promise用法

StevieNowli 8年前發布 | 31K 次閱讀 Node.js 開發

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






 本文由用戶 StevieNowli 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!