ES6的promise的學習

1.Promise的含義:es6

Promise是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最先提出和實現,ES6將其寫進了語言標準,統一了用法,原生提供了Promise對象。編程

所謂Promise,簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果。從語法上說,Promise是一個對象,從它能夠獲取異步操做的消息。Promise提供統一的API,各類異步操做均可以用一樣的方法進行處理。json

Promise對象有如下兩個特色。數組

(1)對象的狀態不受外界影響。Promise對象表明一個異步操做,有三種狀態:Pending(進行中)、Resolved(已完成,又稱Fulfilled)和Rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。這也是Promise這個名字的由來,它的英語意思就是「承諾」,表示其餘手段沒法改變。promise

(2)一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只有兩種可能:從Pending變爲Resolved和從Pending變爲Rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果。就算改變已經發生了,你再對Promise對象添加回調函數,也會當即獲得這個結果。這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。app

 

2.Promise的基本實現dom

var promiseCount=0;
function testPromise(){
    var thisPromiseCount = ++promiseCount;
    var p=new Promise(function(resolve, reject){
        //resolve成功  reject失敗
        setTimeout(function(){
            if(thisPromiseCount<2){
                resolve(thisPromiseCount);
            }else{
                reject(thisPromiseCount)
            }
        },Math.random()*2000+1000);
    });

    p.then(function(val){
        console.log("end: "+val+" Promise被知足了(異步代碼結束)");
        return 'success';
    },function(error){
        console.error('error:'+error+"Promise失敗(異步代碼結束)");
        return 'error'
    }).then(function(val){
        console.log(val);
    })
  }

  testPromise();
 

上面是一個簡單的Promise的基本實現。Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve和reject。resolve表示成功後執行的方法,reject是失敗後執行的方法;new Promise會生成一實例,實例生成後,能夠用then方法分別指定Resolved狀態和Reject狀態的回調函數。then有兩個回調函數,第一個是成功後的回調,第二個是失敗後的回調。異步

 

 

3. Promise.prototype.then異步編程

then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。所以能夠採用鏈式寫法,即then方法後面再調用另外一個then方法。第一個參數是resolved的回調函數,第二個是可選的,rejected回調函數函數

var getJSON = function(url) {
    var promise = new Promise(function(resolve, reject){
        var client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handler;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();

        function handler() {
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText));
            }
        };
    });

    return promise;
};
getJSON("/post/1.json").then(function(post) {
    return getJSON(post.commentURL);
}).then(function funcA(comments) {
    console.log("Resolved: ", comments);
}, function funcB(err){
    console.log("Rejected: ", err);
});

上面的代碼使用then方法,依次指定了兩個回調函數。第一個回調函數完成之後,會將返回結果做爲參數,傳入第二個回調函數。

 

4. Promise.prototype.all

 

Promise.all方法用於將多個Promise實例,包裝成一個新的Promise實例。
數組或者能夠不是數組,但必須具備Iterator接口,且返回的每一個成員都是Promise實例。
(1)只有proList的狀態都變成fulfilled,p的狀態纔會變成fulfilled,此時proList的返回值組成一個數組,傳遞給p的回調函數。
(2)只要proList之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。

ar arr=[1,2,3];
function getPro(a){
    return new Promise(function(resolve,reject){
        if(a>2){
            reject(a);
        }
        resolve(a)
    })
}
var proList=arr.map(function(id){
    return getPro(id);
});

Promise.all(proList).then(function(val){
    console.log(val);
}).catch(function(e){
    console.log('error:'+e);
});

 

上面的例子是一個簡單的promise.all的實現,prolist裏面的三個promise實例,若是三個都返回resolve,那麼就會走第一個then裏面的方法,若是有一個返回reject,那麼久會走到最後的catch方法;

 

4.Promise.prototype.race

Promise.race(),參數跟Promise.all參數同樣,
下面例子只要p一、p2之中有一個實例率先改變狀態,p3的狀態就跟着改變。那個率先改變的Promise實例的返回值,就傳遞給p3的回調函數。p3的回調是看率先改變狀態p1或者p2的promise裏面的函數resolve仍是reject,
若是率先改變狀態的promise是reject,那麼就會走catch回調,反之會走then的第一個回調方法;

 

var p1=new Promise(function(resolve,reject){
    setTimeout(function(){
        console.log(p1);
        resolve('p1:=>success');
    },Math.random()*1000)
});
var p2=new Promise(function(resolve,reject){
    setTimeout(function(){
        console.log(p2);
        reject('p2:=>error');
    },Math.random()*1000)
});

var p3=Promise.race([p1,p2]).then(function(data){
    console.log(p3);
    console.log(data);
}).catch(function(error){
    console.log(p3);
    console.log(error);
});

 

5.Promise.prototype.catch

catch捕獲錯誤 會捕獲全部catch上面的全部then方法裏面的錯誤;

 

/**
 * 因爲沒有指定使用try...catch語句,就冒泡到最外層,成了未捕獲的錯誤。用catch捕獲不了,這個錯誤是在Promise函數體外拋出的。
 * @type {Promise}
 */
var promise = new Promise(function (resolve, reject) {
    resolve("ok");
    setTimeout(function () {
        throw new Error('test')
    }, 0)
});
promise.then(function (value) {
    console.log(value)
}).catch(function (e) {
    console.log(e);
});

/**
 * 須要注意的是,catch方法返回的仍是一個Promise對象,所以後面還能夠接着調用then方法。
 * @returns {Promise}
 */
var someAsyncThing = function () {
    return new Promise(function (resolve, reject) {
        // 下面一行會報錯,由於x沒有聲明
        resolve(x + 2);
    });
};

someAsyncThing()
.catch(function (error) {
        console.log('oh no', error);
})
.then(function () {
        console.log('carry on');
});

 

6.Promise.prototype.resolve和Promis.prototype.reject;

有時須要將現有對象轉爲Promise對象,Promise.resolve方法就起到這個做用, Promise.resolve()有如下三種使用情節,promise.reject跟promise.resolve使用方法同樣;

/**
 *例以下面p1等價於p2
 * @type {Promise.<string>}
 */
var p1=Promise.resolve('foo');
var p2=new Promise(function(resolve,reject){
    resolve('foo');
});
p1.then(function(data){
    console.log(data); //foo
});

/**
 *沒有參數的時候,回掉函數也沒有參數
 * @type {Promise.<string>}
 */
var p3=Promise.resolve();
p3.then(function(){
    console.log('resolve無參數!');
});

/**
 *  當一個對象有then這個參數的時候;
 * @type {Promise.<string>}
 */
var enable={
    then:function(resolve,reject){
        resolve(50);
    }
};
var p4=Promise.resolve(enable);
p4.then(function(s){
    console.log(s);
});

參考網址:http://es6.ruanyifeng.com/#docs/promise

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

相關文章
相關標籤/搜索