js實現promise
阿新 • • 發佈:2018-11-30
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>實現promise</title> </head> <body> <script> function MyPromise(executor){ var that = this this.status = 'pending' // 當前狀態 this.data = undefined this.onResolvedCallback = [] // Promise resolve時的回撥函式集,因為在Promise結束之前有可能有多個回撥新增到它上面 this.onRejectedCallback = [] // Promise reject時的回撥函式集,因為在Promise結束之前有可能有多個回撥新增到它上面 // 更改狀態 => 繫結資料 => 執行回撥函式集 function resolve(value){ if(that.status === 'pending'){ that.status = 'resolved' that.data = value for(var i = 0; i < that.onResolvedCallback.length; ++i){ that.onResolvedCallback[i](value) } } } function reject(reason){ if(that.status === 'pending'){ that.status = 'rejected' that.data = reason for(var i = 0; i < that.onResolvedCallback.length; ++i){ that.onRejectedCallback[i](reason) } } } try{ executor(resolve, reject) // resolve, reject兩個函式可以在外部傳入的函式(executor)中呼叫 } catch(e) { // 考慮到執行過程可能有錯 reject(e) } } // 標準是沒有catch方法的,實現了then,就實現了catch // then/catch 均要返回一個新的Promise例項 MyPromise.prototype.then = function(onResolved, onRejected){ var that = this var promise2 // 值穿透 onResolved = typeof onResolved === 'function' ? onResolved : function(v){ return v } onRejected = typeof onRejected === 'function' ? onRejected : function(r){ return r } if(that.status === 'resolved'){ return promise2 = new MyPromise(function(resolve, reject){ try{ var x = onResolved(that.data) if(x instanceof MyPromise){ // 如果onResolved的返回值是一個Promise物件,直接取它的結果做為promise2的結果 x.then(resolve, reject) } resolve(x) // 否則,以它的返回值做為promise2的結果 } catch(e) { reject(e) // 如果出錯,以捕獲到的錯誤做為promise2的結果 } }) } if(that.status === 'rejected'){ return promise2 = new MyPromise(function(resolve, reject){ try{ var x = onRejected(that.data) if(x instanceof MyPromise){ x.then(resolve, reject) } } catch(e) { reject(e) } }) } if(that.status === 'pending'){ return promise2 = new MyPromise(function(resolve, reject){ self.onResolvedCallback.push(function(reason){ try{ var x = onResolved(that.data) if(x instanceof MyPromise){ x.then(resolve, reject) } } catch(e) { reject(e) } }) self.onRejectedCallback.push(function(value){ try{ var x = onRejected(that.data) if(x instanceof MyPromise){ x.then(resolve, reject) } } catch(e) { reject(e) } }) }) } } MyPromise.prototype.catch = function(onRejected){ return this.then(null, onRejected) } // 以下是簡單的測試樣例: new MyPromise(resolve => resolve(2)).then(value => { console.log(value) }) </script> </body> </html>