Promise對象--Mr.Ember

Promise對象--Mr.Emberajax

摘要json

所謂promise,簡單來講就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)數組

 

promise對象有一下特色:promise

1. 對象的狀態不受外界影響異步

2. 一旦狀態改變就不會再變,任什麼時候候均可以獲得這個結果。async

有了promise對象,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套函數。函數

 

Promise.prototype.then()this

1.then方法下一次的輸入須要上一次的輸出
2.若是一個promise執行完後,返回的仍是一個promise,會把這個promise的執行結果傳遞給下個then中
3.若是then中返回的不是Promise對象而是一個普通值,則會將這個結果做爲下次then的成功結果
4.若是當前then中失敗了 會走下一個then的失敗
5.若是返回的是undefinded無論當前是成功仍是失敗,都會走下一次成功
6.catch是錯誤沒有處理的狀況下才會走
7.then中不寫方法則會穿透,傳入下一個then中
 
Promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)的別名,用於指定發生錯誤時的回調函數。
p.then((val) => console.log('fulfilled:', val))
    .catch((err) => console.log('rejected', err))
//等同於
p.then((val) => console.log('fulfilled:', val))
    .then(null, (err) => console.log('rejected', err))

 

Promise.all()spa

Promise.all將多個Promise實例包裝成一個新的Promise實例。prototype

var  p = Promise.all([p1, p2, p3]);

 

p的狀態由p1,p2,p3決定,分爲兩種狀況:
1. 只有p1, p2, p3的狀態都爲Fulfilled,p的狀態纔會變成Fulfilled,此時p1,p2,p3的返回值成一個數組,傳遞給p的回調函數。
2. 只要p1,p2,p3有一個被rejected,p的狀態就會變成Rejected,此時第一個被rejected的實例的返回值會傳遞給p的回調函數。
 
Promise.race()
Promise.race也是將多個Promise實例包裝成一個新的Promise實例。
var  p = Promise.all([p1, p2, p3]);

 上述代碼中,只要p1, p2, p3有一個實例率先改變狀態,p的狀態就跟着改變。那個率先改變Promise的實例的返回值就傳遞給p的回調函數。

 

Promise.resolve()

有時須要將現有的對象轉爲Promise對象,Promise.resolve方法就起到了這個做用。

var jsPromise = Promise.resolve($ajax('/whatever.json'));

 

上面的代碼會將JQ代碼生成的deferred對象轉換爲新的promise對象。
 
Promise.reject()
Promise.reject會返回一個新的Promise實例,狀態爲Rejected
var p = Promise.reject('出錯了')
//等同於
var p = new Promise((resolve, reject) => reject('出錯了')

p.then(null, function(s){
  console.log(s)
})

 

Promise.done()

不管Promise對象的回調鏈以then的方法仍是catch的方法結尾,只要最後一個放大拋出錯誤,都有可能沒法捕捉到(由於Promise內部錯誤不會冒泡到全局)。爲此咱們能夠提供一個done方法,它老是處於回調鏈的尾端,保證拋出任何可能出現的錯誤。

asyncFunc()
    .then(f1)
    .catch(r1)
    .then(f2)
    .done();

 

內部實現
Promise.prototype.done =  function (onFulfilled, onRejected) {
   this.then(onFulfilled, onRejected)
     .catch(function(reason) {
//全局拋出一個錯誤 setTimeout(()
=> {throw reson}, 0); }) }

 

Promise.finally()

finally方法用於指定Promise對象最後狀態如何都會執行的操做。他與done的區別在於,它接受一個普通的回調函數做爲參數,該函數無論什麼狀態都會執行。

 

模擬實現promise
實現步驟:
1.promise 有個then函數,須要有個callback函數來保存回調函數
2.可能會又多個resolve調用處理,添加一個開關變量,僅使第一個resolve函數可使用
3.當出現多個then函數時,把callback屬性改變成數組格式,保存每個then的回調函數
4.支持then鏈式調用,執行完then函數後返回this便可
5.支持異步的鏈式調用,判斷當前函數是個對象而且還有.then函數,須要繼續調用then,不然跟原來同樣調用
 
 
function MyPromise(fn) {
    var _this = this;

    //用來保存then傳入的回調函數
    this.callback = [];
    //處理 第一個resolve有效
    this.isResolved = false;

    function resolve(val) {
        if(_this.isResolved) return;
        _this.isResolved = true;

        if(_this.callback.length > 0) {
            _this.callback.forEach(item => {
                // func && func(val)
                var res, cb = item.cb, resolve=item.resolve;

                cb && (res = cb(val))
                if(typeof res === 'object' && res.then) {
                    res.then(resolve)
                }else {
                    resolve && resolve(res)
                }
                
            });
        }
    }

    fn(resolve);
}

MyPromise.prototype.then = function(cb) {
    var _this = this;
    return new MyPromise(function(resolve) {
        _this.callback.push({
            cb: cb,
            resolve: resolve
        })
    })
}

var  p = new MyPromise(function(resolve) {
    console.log(1)
    setTimeout(function() {
        resolve(2)
        resolve(4)
        resolve(5)
        resolve(6)
    }, 1000)
})

p.then(function(val) {
    console.log(val)
    return new MyPromise(function(resolve) {
        setTimeout(function() {
            resolve(val + 1)
        }, 1000)
    })
}).then(function(val) {
    console.log(val)
})

 打印結果

 

 先打印1,過了一秒打印2,再過一秒打印3

相關文章
相關標籤/搜索