JS手寫一個自定義Promise操作示例
阿新 • • 發佈:2020-03-17
本文例項講述了JS手寫一個自定義Promise操作。分享給大家供大家參考,具體如下:
經常在面試題中會看到,讓你實現一個Promsie,或者問你實現Promise的原理,所以今天就嘗試利用class類的形式來實現一個Promise
為了不與原生的Promise命名衝突,這裡就簡單命名為MyPromise.
class MyPromise { constructor(executor) { let _this = this this.state = 'pending' // 當前狀態 this.value = undefined // 儲存成功的值 this.reason = undefined // 儲存失敗的值 // 利用釋出訂閱模式,讓Promise支援非同步 this.onFulfilledFunc = [] // 儲存成功的回撥 this.onRejectedFunc = [] // 儲存失敗的回撥 function resolve (value) { // Promise物件已經由pending狀態改變為了成功態(resolved)或是失敗態(rejected)就不能再次更改狀態了。因此我們在更新狀態時要判斷,如果當前狀態是pending(等待態)才可更新 if (_this.state === 'pending') { _this.value = value //依次執行成功回撥 _this.onFulfilledFunc.forEach(fn => fn(value)) _this.state = 'resolved' } } function reject (reason) { // Promise物件已經由pending狀態改變為了成功態(resolved)或是失敗態(rejected)就不能再次更改狀態了。因此我們在更新狀態時要判斷,如果當前狀態是pending(等待態)才可更新 if (_this.state === 'pending') { _this.reason = reason //依次執行失敗回撥 _this.onRejectedFunc.forEach(fn => fn(reason)) _this.state = 'rejected' } } try { // 當例項化Promise時,建構函式中就要馬上呼叫傳入的executor函式執行 executor(resolve,reject) } catch (error) { reject(error) } } _resolvePromise (promise2,x,resolve,reject) { // 如果返回了自己的Promise物件,狀態永遠為等待態(pending),再也無法成為resolved或是rejected,程式會死掉,因此首先要處理它 if (promise2 === x) { reject(new TypeError('Promise存在迴圈引用')) } if (x !== null && (typeof x === 'object' || typeof x === 'function')) { // x可能是一個promise try { let then = x.then if (typeof then === 'function') { then.call(x,(y) => { _resolvePromise(promise2,y,reject) }) } else { resolve(x) } } catch (err) { reject(err) } } else { //否則是個普通值 resolve(x) } } then (onFulfilled,onRejected) { let promise2 onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (val) { return val } onRejected = typeof onRejected === 'function' ? onRejected : function (reason) { throw reason } if (this.state === 'resolved') { promise2 = new MyPromise((resolve,reject) => { setTimeout(() => { try { let x = onFulfilled(this.value) this._resolvePromise(promise2,reject) } catch (error) { reject(error) } },0); }) } if (this.state === 'rejected') { promise2 = new MyPromise((resolve,reject) => { setTimeout(() => { try { let x = onRejected(this.reason) this._resolvePromise(promise2,0); }) } if (this.state === 'pending') { promise2 = new MyPromise((resolve,reject) => { this.onFulfilledFunc.push(() => { setTimeout(() => { try { let x = onFulfilled(this.value) this._resolvePromise(promise2,reject) } catch (error) { reject(error) } },0); }) this.onRejectedFunc.push(() => { setTimeout(() => { try { let x = onRejected(this.reason) this._resolvePromise(promise2,0); }) }) } return promise2 } }
執行測試:
var promise = new MyPromise((resolve,reject) => { console.log(1) setTimeout(() => { resolve(2) },1000); console.log(3) }).then(value => console.log(value))
結果真香:
感興趣的朋友可以使用線上HTML/CSS/JavaScript程式碼執行工具:http://tools.jb51.net/code/HtmlJsRun測試上述程式碼執行效果。
更多關於JavaScript相關內容感興趣的讀者可檢視本站專題:《javascript面向物件入門教程》、《JavaScript錯誤與除錯技巧總結》、《JavaScript資料結構與演算法技巧總結》、《JavaScript遍歷演算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程式設計有所幫助。