JavaScript Promise 告別異步亂嵌套

什麼是Promise?

在說Promise以前, 不得不說一下,JavaScript的嵌套的回調函數

在JavaScript語言中, 不管是寫瀏覽器端的各類事件回調、ajax回調,仍是寫Node.js上的業務邏輯,不得不面對的問題就是各類回調函數。回調函數
少了還好,一旦多了起來並且必須講究執行順序的話,回調函數開始嵌套,那代碼的噁心程度是至關不符合常人的線性思惟的。git

我的認爲Promise就是爲了把JS複雜的嵌套轉換成常人思惟的線性代碼。es6

// 就像下面這樣:
// 你不在意下面這三個ajax的執行順序還好
// 若是你在意順序呢?
$.get('url', function(){
    
}, 'json');
$.get('url1', function(){
    
}, 'json');
$.get('url2', function(){
    
}, 'json');

// 就像這樣?
$.get('url', function(){
    $.get('url1', function(){
        $.get('url2', function(){
    
        }, 'json');
    }, 'json');
}, 'json');


// 下面是我最近寫的一段Node.js的代碼
// 其實這個嵌套也不算多
// 若是業務邏輯至關複雜起來呢?
// 嵌套20 30層?
var adminIndex = function(params, callback){
  storeAdmin.getApiTokens(function(err, tokens){
    if ( err ) { callback(err); return; }
    storeAdmin.getApiServices(function(err, apiServices){
      if ( err ) { callback(err); return; }
      storeAdmin.getSocketioServices(function(err, socketioServices){
        if ( err ) { callback(err); return; }
        callback(0, {
          status : true,
          data : {
            api_tokens : tokens,
            api_services : apiServices,
            socketio_services : socketioServices
          }
        });
      });
    });
  });
};

說了這麼多, 到底什麼是Promise呢?

其實, Promise就是一個類,並且這個類已經成爲ES6的標準,這個類目前在chrome3二、Opera1九、Firefox29以上的版本都已經支持了,要想在全部瀏覽器上都用上的話就看看es6-promise吧。github

那Promise怎麼用呢?

那看一段很簡單的代碼,請注意閱讀代碼中的註釋。ajax

var val = 1;

// 咱們假設step1, step2, step3都是ajax調用後端或者是
// 在Node.js上查詢數據庫的異步操做
// 每一個步驟都有對應的失敗和成功處理回調
// 需求是這樣,step一、step二、step3必須按順序執行
function step1(resolve, reject) {
    console.log('步驟一:執行');
    if (val >= 1) {
        resolve('Hello I am No.1');
    } else if (val === 0) {
        reject(val);
    }
}

function step2(resolve, reject) {
    console.log('步驟二:執行');
    if (val === 1) {
        resolve('Hello I am No.2');
    } else if (val === 0) {
        reject(val);
    }
}

function step3(resolve, reject) {
    console.log('步驟三:執行');
    if (val === 1) {
        resolve('Hello I am No.3');
    } else if (val === 0) {
        reject(val);
    }
}

new Promise(step1)
    .then(function(val) {
        console.info(val);
        return new Promise(step2);
    })
    .then(function(val) {
        console.info(val);
        return new Promise(step3);
    })
    .then(function(val)  {
        console.info(val);
        return val;
    })
    .then(function(val) {
        console.info(val);
        return val;
    });

// 執行以後將會打印
步驟一:執行
Hello I am No.1
步驟二:執行
Hello I am No.2
步驟三:執行
Hello I am No.3
Hello I am No.3

Promise到底解決什麼問題?

正如上面代碼所示,我的認爲Promise的意義就在於then鏈式調用,他避免了異步函數之間的層層嵌套,將原來異步函數的嵌套函數轉變爲便於閱讀和理解的鏈式步驟關係chrome

Promise的主要用法就是將各個異步操做封裝成好多Promise,而一個Promise只處理一個異步操做。最後將各個Promise用鏈式調用寫法串聯,在這樣處理下,若是異步邏輯之間先後關係很重的話,你也不須要層層嵌套,只須要把每一個異步邏輯封裝成Promise鏈式調用就能夠了。數據庫

Promise經常使用的關鍵點

在Promise定義時,函數已經執行了

Promise構造函數只接受一個參數,即帶有異步邏輯的函數,這個函數在new Promise時已經執行了。只不過在沒有調用then以前不會resolve或rejectjson

在then中的resolve方法中如何return?

在then方法中一般傳遞兩個參數, 一個resolve函數, 一個reject函數(暫時不討論,就是出錯時運行的函數罷了)。resolve函數必須返回一個值才能把鏈式調用進行下去,並且這個值返回什麼是有很大講究的。後端

  • resolve返回一個新的Promise
    返回一個新Promise以後再調用的then就是新的Promise中的邏輯了。api

  • resolve返回一個值
    返回一個值會傳遞到下一個then的resolve方法參數中。promise

相關文章
相關標籤/搜索