爲啥要說 promise ?javascript
由於這是前端必需要掌握的一個知識,吹逼必備前端
Promise 是JavaScript的第一個異步標準模型,一個包含傳遞信息與狀態的對象,emmm...它的英語意思是承諾.
so 它擁有的特色也有承諾的意思(兄弟們,拿好筆記本,劃重點):java
那 Promise 爲何會出現呢?c++
Promise以前的時候,咱們用三個手段解決異步問題面試
回調函數是最簡單的異步方式,它比較容易理解和部署,也是咱們最常使用的,可是缺點也很明顯,不利於代碼的閱讀和維護,流程混亂。數組
觀察者模式和事件機制很少說,就是適用於屢次同類型的異步,不適用一次性的異步promise
而 Promise 能夠將異步操做以同步操做的流程表達出來,併發
先來個最簡單的Prmise異步
const p = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve('你好,兄弟') //設置成resolve狀態 便是成功 },1e3) }) p.then(res=>{ console.log(res) // 1s後輸出 ==> 你好,兄弟 })
是否是看起來 so easy ?函數
下面咱們來實現一下最簡單的 Promise。 Promise只是一個普通的構造函數,用es3的語法也能夠實現
因此在ie6均可以用,不過咱們就使用class來實現了
class myPromise { constructor(fn) { this.state = 'PENDING'; this.message = ''; this.fns = []; fn(this.resolve.bind(this), this.reject.bind(this)); } resolve(res) { this.state = 'FULFILLED'; this.message = res; this._onChange(); } reject(err) { this.state = 'REJECTED'; this.message = err; this._onChange(); } then(onResolved, onRejected) { let self = this; return new myPromise((resolve, reject) => { self.fns.push([onResolved, onRejected, resolve, reject]); self._onChange(); }); } _onChange() { this.state !== 'PENDING' && this.fns.forEach(v => { this._change(v); }); } _change(arr) { let onResolved = arr[0], onRejected = arr[1], resolve = arr[2], reject = arr[3]; switch (this.state) { case 'FULFILLED': if (typeof onResolved === 'function') { resolve(onResolved.call(null, this.message)); } else { resolve(this.message); } break; case 'REJECTED': if (typeof onRejected === 'function') { resolve(onRejected.call(null, this.message)); } else { reject(this.message); } break; default: break; } } } //老哥們注意,這只是我本身寫的一個簡略的 Promise , 並非真正的 Promise 的實現 const p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('你好,兄弟'); //1s後設置成resolve狀態 便是成功 }, 1e3); }); p.then(res => { console.log(res); // 1s後輸出 ==> 你好,兄弟 return '1'; }) .then(res => { console.log(res); // 1s後輸出 ==> '1' }) .then(res => { console.log(res); // 1s後輸出 ==> undefined });
Promise 還提供一個快速實例化 Promise ,能夠傳入參數而且立刻觸發 Promise 鏈的執行
Promise.resolve = data => new Promise((resolve, reject) => { resolve(data); }); Promise.reject = err => new Promise((resolve, reject) => { reject(err); });
Promise 還提供 all / race 用來處理數據的併發和競爭,要求是傳一個 Promise 數組做爲參數,而後返回一個新的 Promise
all 是所有處理後再統一處理
Promise.all = arr => new Promise((resolve, reject) => { let c = 0, l = arr.length, result = []; l === 0 && resolve(result); arr.forEach(pro => { Promise.resolve(pro).then(res => { result.push(res); c++; c === l && resolve(result); }, err => { reject(err); } ); }); });
race 則是誰異步時間短誰就會被處理
Promise.race = arr => new Promise((resolve, reject) => { arr.forEach(pro => { Promise.resolve(pro).then(resolve, reject); }); });
Promise 的 then 函數咱們也知道是怎麼用的,它始終以當前的結果返回一個新的Promise
而以前咱們說到 Promise 的錯誤是異步的 也直接調用到 reject,
那咱們在 resolve 或者 reject 出現錯誤應該怎麼作呢? Promise 還提供一個catch 用來捕捉錯誤
Promise.catch = reject => this.then(undefined,reject)
怎麼用呢?
const p = new Promise((resolve, reject) => { //執行操做 //..略 }); p.then(resolve, reject) .then(resolve, reject) .then(resolve, reject) .catch(err => { //若是以上出現錯誤會直接傳遞到此處執行錯誤處理 });
說是異步,那麼和咱們最原始的 setTimeout 有什麼區別呢?
先讓咱們看一道面試題目
console.log('a'); setTimeout(() => { console.log('b'); }); console.log('c'); new Promise((resolve, reject) => { console.log('d'); resolve('e'); }).then(res => { console.log(res); }); console.log('f');
輸出順序是什麼呢 ?
a => c => d => f => e => b
這裏就要關係到js的 EventLoop 機制了,這裏並不細說,只是拋個引子,有興趣的朋友能夠去看看相關文章
到這裏就結束了,老哥們,要去搬磚了
若是發現文章有什麼問題,能夠留言哦