JS異步那些事 三 (Promise)

JS異步那些事 一 (基礎知識)
JS異步那些事 二 (分佈式事件)
JS異步那些事 三 (Promise)
JS異步那些事 四(HTML 5 Web Workers)
JS異步那些事 五 (異步腳本加載)javascript

Promise,Deferred 對象

前戲

先來談談jquery中的promise的使用,來看一個例子
本來寫一個小動畫咱們多是這樣的java

<script type="text/javascript"> 
$('.animateEle').animate({
  opacity:'.5'
}, 4000,function(){
  $('.animateEle2').animate({
    width:'100px'
  },2000,function(){
    $('.animateEle3').animate({
      height:'0'
    },2000);
  });
});
</script>

可是若是咱們使用promis對象的話,就可使得代碼更加簡單易懂jquery

<script type="text/javascript"> 
var animate1 = function() {
  return $('.animateEle1').animate({opacity:'.5'},4000).promise();
};
var animate2 = function() {
  return $('.animateEle2').animate({width:'100px'},2000).promise();
};
var animate3 = function(){
  return $('.animateEle3').animate({height:'0'},2000).promise();
};
$.when(animate1()).then(animate2).then(animate3);
</script>

看了上面的例子大概對promise的做用有必定的瞭解了吧,那就來講說promis的原理吧es6

Promise對象方法

對於DOM,動畫,ajax相關方法,均可以使用 promise 方法。調用 promise 方法,返回的是 promise 對象。能夠鏈式調用 promise 方法。ajax

好比jquery中的ajax的 $.post $.get $.ajax 等方法,實際上都是默認調用了promise方法,而後返回了一個promise對象segmentfault

promise對象常見的方法有三個 : done , fail , then 。api

<script type="text/javascript"> 
$.get('/',{}).done(function(data){
    console.log('success');
}).fail(function(){
    console.log('fail');
});
</script>

jquery 這裏的接口方法太多了,就跟早期的事件方法綁定同樣, live , delegate , bind ,最終仍是歸爲 onpromise

deferred對象方法

deferred 對象呢,也就是使用 $.Deferred() 方法,以及 $.when() 等方法創造出來的對象,它能夠理解爲一個升級版特殊的的promise對象
來看看一個例子異步

<script type="text/javascript"> 
  var  promisepbj = new $.Deferred();

     promisepbj.done(function() {
      console.log('haha,done');
    }).fail(function() {
      console.log('失敗了');
    }).always(function(res) {
      console.log('我老是被執行啦');
    });

    //使用resolve或者reject就能夠調用defferred對象了
    promisepobj.resolve();
    //promisepobj.reject();

resolve 方法會觸發 done 的回調執行, reject 會觸發 fail 的回調,對於 always 方法,deferred 對象,不管是 resolve 仍是 reject ,都會觸發該方法的回調。分佈式

ES6 Promise

前面講了不少jquery的promise實現,$.Deferred 和 ES2015 的 Promise 是不一樣的東西,由於前者不符合 Promises/A+ 規範。 Promise 對象在 EMCAScript 2015 當中已經成爲標準。如今要來談談立刻要成爲主流趨勢的es6原生promise對象,首先貼一個很詳細的es6 promise的小書,基本你知道的不知道都在裏面 http://liubin.org/promises-book/#introduction

把promise解釋的很清楚的文章不少,我自認爲我寫不到他們那麼好,索性乾脆把阮一峯大神的文章貼出來 http://es6.ruanyifeng.com/#docs/promise
我就來個簡化版本的吧,用最短的字數來入個門。

定義:

謂Promise,簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果。
特色:

  1. 有三種狀態:Pending(進行中)、Resolved(已完成,又稱Fulfilled)和Rejected(已失敗)。

  2. 一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只有兩種可能:從Pending變爲Resolved和從Pending變爲Rejected。只要這兩種狀況發生,狀態就凝固了

基本用法

<script type="text/javascript"> 
var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操做成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
</script>

Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve和reject。

<script type="text/javascript"> 
function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}

timeout(100).then((value) => {
  console.log(value);
});
</script>

上面代碼中,timeout方法返回一個Promise實例,表示一段時間之後纔會發生的結果。過了指定的時間(ms參數)之後,Promise實例的狀態變爲Resolved,就會觸發then方法綁定的回調函數。

異常處理

  異常處理一直是回調的難題,而promise提供了很是方便的catch方法:在一次promise調用中,任何的環節發生reject,均可以在最終的catch中捕獲到:

Promise.resolve().then(function(){
    return loadImage(img1);
}).then(function(){
    return loadImage(img2);
}).then(function(){
    return loadImage(img3);
}).catch(function(err){
    //錯誤處理
})

基本的 api

Promise.resolve()
Promise.reject()
Promise.prototype.then()
Promise.prototype.catch()
Promise.all()
Promise.race()

小結

具體的不少的用法能夠參考阮一峯的 http://es6.ruanyifeng.com/#docs/promise 入門教程,還有就是上面提到的電子書 http://liubin.org/promises-book/#introduction

相關文章
相關標籤/搜索