異步編程——promise

異步編程——promise

定義

Promise是異步編程的一個解決方案,相比傳統的解決方法——回調函數,使用Promise更爲合理和強大,避免了回調函數之間的層層嵌套,也使得代碼結構更爲清晰,便於維護。Promise 是一個對象,從他能夠獲取異步操做的消息,他也是一個容器,裏面包含着事件結束以後要進行的操做。javascript

特色

Promise對象有兩個特色:java

  • 對象的狀態不收外界干擾。Promise對象有三種狀態:pending(進行中)、resolved(已完成)、rejected(已失敗),具體處於哪種狀態是由異步操做的結果來決定的,其餘的任何操做都沒法改變這個狀態。
  • 一旦狀態改變了,就不會再有其餘的改變了,任什麼時候候都能獲得這個結果。Promise對象狀態的改變有兩種:1>.pending狀態到resolved狀態;2>.pending狀態到rejected狀態;

用法

Promise是一個構造函數,生成一個實例。ajax

var promise = new Promise(function(resolve,reject){
  if(/異步成功/){
    resolve(val);
  }else{
     reject(val);
  }
});
promise.then(function(val){
/成功後執行的函數/
},function(error){
/失敗後執行的函數/
});

Promise構造函數接收一個函數做爲參數,這個函數有兩個參數resolve、reject,這兩個參數也是兩個函數,有javascript引擎提供,不須要本身實現。其中,resolve函數的做用是將Promise對象的狀態由"進行中"變爲"已完成",在異步操做成功的時候調用,並將異步操做的結果以參數的形式傳出,就是上例中的val。reject函數的做用是將Promise對象的狀態由"進行中"變爲"已失敗",在異步操做失敗的時候調用,並將操做失敗的錯誤已參數的形式傳出。編程

Promise的實例能夠調用then方法,then方法有兩個函數做爲參數,第一個函數是Promise對象狀態變爲resoloved時執行的函數,第二個函數是Promise對象狀態變爲rejected時執行的函數,第二個參數是可選的。數組

一個典型的例子:異步讀取文件promise

function readFileFn(filename){
  return new Promise(function(resolve,reject){
    fs.readfile(filename,function(err,data){
      if(err){
        reject(err);
      }else{
        resolve(data);
      }
    });
  });
}
readFileFn("./test.txt").then(function(data){
  console.log(data.toString());
  //其餘操做...
  },function(err){
    console.log(err);
});

then方法能夠採用鏈式的寫法,即:異步

promise.then(...).then(...).then(..)異步編程

具體的例子:函數

var promise = new Promse(function(resolve,reject){
    resolve(1);    //將Promise對象的狀態改成resolved,並傳遞參數1
});
promise.then(function(val){
    console.log(val);  // 1
    return val*3;
}).then(function(val){
    console.log(val);  //3
    return val*3;
}).then(function(val){
    console.log(val);  //9
});

Promise對象的一些其餘方法

  • Promise.prototype.catch:用於指定發生錯誤時的回調函數,一般的用法是在then方法裏省略第二個參數,而後在鏈式調用的尾部使用catch方法來捕獲異步操做或者then方法中的錯誤;
readFileFn("./test.txt").then(function(data){
  console.log(data.toString());
  //其餘操做...
}).catch(function(err){
    console.log(err);
})
//另外一種用法
var promise = new Promise(function(resolve,reject){
    reject(new Error("test"));
});
promise.then(function(val){
    //...
}).catch(function(err){
    console.log(err);
    //..
});
  • Promise.all():次方法用於將多個Promise實例包裝成一個新的Promise實例。Promise.all()方法接收一個數組做爲參數:

var p = Promise.all([a,b,c]);  //a,b,c都是Promise的實例prototype

p最終的狀態由a,b,c三者決定:

1>.當a,b,c的狀態都是resolved時,p的狀態纔是resolved,此時a,b,c的返回值組成一個數組,傳給p的回調函數。

2>.只要 a,b,c中有一個狀態時reject,p的狀態就是reject,此時一個reject的實例的返回值會傳遞給p的回調函數。

var promises = [1,2,3,4].map(function(id){
    return readFileFn("./test"+id+".txt");  //readFileFn()是上面聲明過的函數
});
Promise.all(promises).then(function(val){
    //...
}).catch(function(err){
    //...
});
  • Promise.race():一樣是將多個Promise實例包裝成一個新的Promise實例,與Promise.all()方法相似;
  • Promise.resolve():將一個非Promise對象轉換爲一個Promise對象,

var promise = Promise.resolve($.ajax("./test.txt"));

Promise.resolve()有四種類型的參數:

1>.Promise實例,那麼函數不會對參數作任何修改,原樣返回;

2>.普通對象,如同上例,會轉換成一個promise對象返回;

3>.非對象,即普通的變量,好比"hello"、2 等等,此時會返回一個新的Promise實例,狀態爲resolved(),"hello"會以參數的形式傳給then的第一個方法;

var p = Promise.resolve("hello");
p.then(function(val){        //此函數會當即執行
  console.log(val);  //hello
});

4>.不帶參數,會直接返回一個Resolved狀態的Promise對象。

  • Promise.reject():返回一個狀態爲rejected的實例,參數相似於Promise.resolve()方法的第三種參數。
  • done():Promise內部的錯誤不會冒泡到全局,因此,若是回調鏈的最後一個出現錯誤,就沒法被捕獲,因此有了done()方法,位於回調鏈的最尾端,用於捕獲錯誤。

promise.then(function(){}).then(function(){}).catch(function(){}).done();

  • finally():指定無論Promise最後的狀態如何都會執行的操做,他與done()的區別是能夠接受一個普通的回調函數做爲參數,且該函數必定會執行。
相關文章
相關標籤/搜索