1. 程式人生 > 實用技巧 >Promise簡易版實現

Promise簡易版實現

/**
 * 自定義簡易版Promise
 * 
 */
class EasyPromise {
    static resolveCbStatic = undefined; // 供EasyPromise.all等靜態方法使用
    static rejectCbStatic = undefined; // 供EasyPromise.all等靜態方法使用

    resolveCb = undefined; // status == resolved 的回撥
    rejectCb = undefined; // status == reject 的回撥
    finallyCb = undefined; //
status == resolved || status == reject 的回撥,此方法無入參,不依賴於 Promise 的執行結果 resolveData = undefined; // status == resolved 資料儲存 rejectData = undefined; // status == reject 資料儲存 status = 'pending'; // 記錄Promise傳入的非同步任務狀態 constructor (fn) { if (!fn || typeof fn != 'function') { console.log(
'EasyPromise方法傳參無效') return false; } this._resolve = this._resolve.bind(this) this._reject = this._reject.bind(this) this.then = this.then.bind(this) this.catch = this.catch.bind(this) this.finally = this.finally.bind(this) fn(this
._resolve, this._reject) } _resolve (data) { if (this.status == 'pending') { this.status = 'resolved'; this.resolveData = data; this.resolveCb && this.resolveCb(data) this.finallyCb && this.finallyCb() } } _reject (err) { if (this.status == 'pending') { this.status = 'rejected'; this.rejectData = err; this.rejectCb && this.rejectCb(data) this.finallyCb && this.finallyCb() } } then (fn) { if (!fn || typeof fn != 'function') { console.log('then方法傳參無效') return false; } // 鏈式程式設計(關鍵程式碼) return new EasyPromise((resolve, reject) => { this.resolveCb = () => { let ret = fn(this.resolveData); if (ret && ret.constructor == EasyPromise) { ret.then((data) => { resolve(data) }) } else { resolve(ret) } }; if (this.status == 'resolved') { this.resolveCb(this.resolveData) } }) } catch (fn) { if (!fn || typeof fn != 'function') { console.log('catch方法傳參無效') return false; } this.rejectCb = fn; if (this.status == 'rejected') { this.resolveCb(this.rejectData) } return this; // 鏈式程式設計 } finally (fn) { if (!fn || typeof fn != 'function') { console.log('finally方法傳參無效') return false; } this.finallyCb = fn; if (this.status == 'resolved' || this.status == 'rejected') { this.finallyCb() } } static all (promiseList) { if (!promiseList || Object.prototype.toString.call([]) != '[object Array]') { console.log('all方法傳參無效') return false; } let len = promiseList.length; let count = 0; let res = []; let catchFlag = false; let invalid = false; promiseList.forEach((item) => { if (!item || item.constructor != EasyPromise) { invalid = true; } }) if (invalid) { console.log('promiseList 內包含不是EasyPromise的例項') return false; } promiseList.forEach((item, index) => { if (catchFlag) { return false; } item.then((data) => { count += 1; res[index] = data; if (len == count) { // 所有任務處理成功 this.resolveCbStatic(res) } }).catch(() => { // 任一任務出現錯誤 catchFlag = true; this.rejectCbStatic(`all 方法呼叫錯誤, 對應索引-${index}`) }) }) return this; } static then (fn) { if (!fn || typeof fn != 'function') { console.log('then方法傳參無效') return false; } this.resolveCbStatic = fn; return this; } static catch (fn) { if (!fn || typeof fn != 'function') { console.log('catch方法傳參無效') return false; } this.rejectCbStatic = fn; } static race (promiseList) { if (!promiseList || Object.prototype.toString.call([]) != '[object Array]') { console.log('all方法傳參無效') return false; } let invalid = false; let status; promiseList.forEach((item) => { if (!item || item.constructor != EasyPromise) { invalid = true; } }) if (invalid) { console.log('promiseList 內包含不是EasyPromise的例項') return false; } promiseList.forEach((item, index) => { item.then((data) => { if (status == 'end') { return false; } status = 'end'; this.resolveCbStatic(data) }).catch((err) => { this.rejectCbStatic(`race 方法呼叫錯誤`) }) }) return this; } } // 測試EasyPromise new EasyPromise((resolve, reject) => { let data = { value: '我是非同步響應的資料' } setTimeout(function () { let flag = true; if (flag) { resolve(data) } else { reject('非同步處理異常') } }, 1000) }) .then((data) => { console.log(`響應資料為:`, data) return '哈哈哈' }) .then((data) => { console.log(data, '第二個then的資料') return new EasyPromise((resolve, reject) => { setTimeout(function () { resolve('呵呵呵') }, 1000) }) }) .then((data) => { console.log(data, '第三個then的資料') }) .catch((err) => { console.log(`發生錯誤:${err}`) }) .finally((data) => { console.log(`我是finally觸發`) }) // 測試 EasyPromise.all 方法 let promise1 = new EasyPromise((resolve, reject) => { setTimeout(function () { resolve('呵呵呵') }, 2000) }) let promise2 = new EasyPromise((resolve, reject) => { setTimeout(function () { resolve('哈哈哈') }, 1000) }) EasyPromise.all([ promise1, promise2 ]) .then((data) => { console.log(data) }) .catch((err) => { console.log(err) }) // 測試 EasyPromise.race 方法 let promise3 = new EasyPromise((resolve, reject) => { setTimeout(function () { resolve('呵呵呵') }, 2000) }) let promise4 = new EasyPromise((resolve, reject) => { setTimeout(function () { resolve('哈哈哈') }, 1000) }) EasyPromise.race([ promise3, promise4 ]) .then((data) => { console.log(data) }) .catch((err) => { console.log(err) })