摘要:使用及原理分析通過關鍵字創建實例接受一個參數方法返回兩個方法可用通過在方法中通過調用使成功或調用使失敗來控制狀態中可以執行同步代碼也可以執行異步代碼原型對象上有方法供實例調用方法接受兩個參數默認為一個函數默認為一個函數當狀態為時執行用戶傳入
promise使用及原理分析:
通過new關鍵字創建promise實例, 接受一個executor參數, executor方法返回兩個方法 resolve, reject, 可用通過在executor方法中通過調用resolve(使成功)或調用reject(使失敗),來控制promise狀態
let p = new Promise((resolve, reject) => { resolve(100) })
executor中可以執行同步代碼也可以執行異步代碼
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve(100) }) })
promise原型對象上有then方法供promise實例調用, then方法接受兩個參數onFulfilled, onRejected
onFulfilled默認為一個函數 data => data
onRejected默認為一個函數 err => {throw err}
當promise狀態為fulfilled時, 執行用戶傳入的onFulfilled方法
當promise狀態為rejected時, 執行用戶傳入的onRected方法
當用戶創建promise對象時采用異步,那么執行then方法時沒有調用resolve方法或reject方法,所以promise狀態依然為pending狀態,所以需要在then方法中采取發布訂閱模式,先保存then方法傳來的onFulfilled和onReje
又因為同一個promise實例可以調用多次then方法,從而傳多個onFulfilled和onRected,所以發布訂閱采用數組保存
onFulfilled和onRejected方法中可能throw Error, 所以在執行onFulfilled和onRejected時需要try catch捕獲
then方法返回一個新的Promise實現鏈式編程
統一判斷then方法傳入的onFulfilled方法和onRejected方法中return的類型(resolvePromise)
p.then(data => { console.log(data) }, err => { console.log(err) })
let p1 = p.then(data => { return p1 // 報類型錯誤 })
p.then(data => { return new Promise((resolve, reject) => { resolve(100) }) })
catch方法接受一個錯誤回調,可以用then方法實現(語法糖)
ES2018 中新增finally方法 也可以通過then方法實現(語法糖) finally要實現值得穿透, finally前如果有then方法,其返回值要穿過finally方法傳給之后的then
p.then(data => { return 100 }).finally(() => { console.log("finally") }).then(data => { console.log(data) // 100 })
all, race 方法都接受一個promise數組
all方法要所有promise都返回才resolve一個全部是成功態的數組,只要有一個rejected就直接reject
race方法只要有一個promise resolve就直接resolve
完整代碼如下:class Promise { constructor(executor) { this.status = Promise.PENDING this.value = undefined this.reason = undefined // 發布訂閱的存儲器onResolvedCallbacks, onRejectedCallbacks this.onResolvedCallbacks = [] this.onRejectedCallbacks = [] this.initBind() this.init(executor) } initBind() { this.resolve = this.resolve.bind(this) this.reject = this.reject.bind(this) } init(executor) { // 防止executor中拋錯 try { executor(this.resolve, this.reject) } catch (e) { this.reject(e) } } resolve(data) { // 如果resolve中傳入一個promise, 那么返回改promise結果 if (data instanceof Promise) data.then(this.resolve, this.reject) if (this.status === Promise.PENDING) { this.status = Promise.FULFILLED this.value = data this.onResolvedCallbacks.forEach(fn => fn()) } } reject(reason) { if (this.status === Promise.PENDING) { this.status = Promise.REJECTED this.reason = reason this.onRejectedCallbacks.forEach(fn => fn()) } } then(onFulfilled, onRejected) { const fulfilledHandle = (resolve, reject) => { // 此處用setTimeout異步才能拿到promise2 setTimeout(() => { try { let x = onFulfilled(this.value) Promise.resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) } const rejectHandle = (resolve, reject) => { setTimeout(() => { try { let x = onRejected(this.reason) Promise.resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) } // onFulfilled和onRejected定義默認值 onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason } let promise2 = new Promise((resolve, reject) => { if (this.status === Promise.FULFILLED) { fulfilledHandle(resolve, reject) } if (this.status === Promise.REJECTED) { rejectHandle(resolve, reject) } if (this.status === Promise.PENDING) { this.onResolvedCallbacks.push(() => { fulfilledHandle(resolve, reject) }) this.onRejectedCallbacks.push(() => { rejectHandle(resolve, reject) }) } }) // 返回一個新的promise return promise2 } catch (onRejected) { return this.then(null, onRejected) } static resolve() { return new Promise((resolve, reject) => { resolve() }) } static reject() { return new Promise((resolve, reject) => { reject() }) } finally(callback) { return this.then( data => Promise.resolve(callback()).then(() => data), err => Promise.resolve(callback()).then(() => { throw err }) ) } static all(promises) { return new Promise((resolve, reject) => { let result = [] let count = 0 const setResult = (key, value) => { result[key] = value if (++count === promises.length) { resolve(result) } } for (let i = 0; i < promises.length; i++) { let current = promises[i] if (Promise.isPromise(current)) { current.then(data => { setResult(i, data) }, reject) } else { setResult(i, current) } } }) } static race(promises) { return new Promise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { let current = promises[i] if (Promise.isPromise(current)) { current.then(resolve, reject) } else { resolve(current) } } }) } } Promise.PENDING = "pending" Promise.FULFILLED = "fulfilled" Promise.REJECTED = "rejected" Promise.resolvePromise = (promise2, x, resolve, reject) => { // called防止他人的promise即執行resolve又執行 reject let called if (promise2 === x) throw new TypeError("xxx") if (typeof x === "function" || typeof x === "object" && x !== null) { try { let then = x.then if (typeof then === "function") { then.call(x, y => { if (called) return called = true // 遞歸解析,總有一個結果then方法返回一個普通值 Promise.resolvePromise(promise2, y, resolve, reject) }, e => { if (called) return called = true reject(e) }) } else { resolve(x) } } catch (e) { if (called) return called = true reject(e) } } else { resolve(x) } } Promise.isPromise = (obj) => { return typeof obj === "function" || typeof obj === "object" && obj !== null && obj.then && typeof obj.then === "function" } // 延遲對象 Promise.deferred = () => { const defer = {} defer.promise = new Promise((resolve, reject) => { defer.resolve = resolve defer.reject = reject }) return defer } module.exports = Promise
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104774.html
摘要:本文同時也發布在我的博客上,歡迎之前也手寫過簡單的,這次則是為了通過官方的測試集,借鑒了一些下載量較多的,改了幾遍,終于是通過了規范的個測試用例如何測試測試庫地址在這,大家在寫完自己的后,不妨也去測試一下,檢驗自己的是否符合規范。 本文同時也發布在我的github博客上,歡迎star~ 之前也手寫過簡單的promise,這次則是為了通過官方的Promise A+測試集,借鑒了一些下載量...
摘要:手寫一款符合規范的長篇預警有點長,可以選擇性觀看。初始狀態是,狀態可以有或者不能從轉換為或者從轉換成即只要由狀態轉換為其他狀態后,狀態就不可變更。 手寫一款符合Promise/A+規范的Promise 長篇預警!有點長,可以選擇性觀看。如果對Promise源碼不是很清楚,還是推薦從頭看,相信你認真從頭看到尾,并且去實際操作了,肯定會有收獲的。主要是代碼部分有點多,不過好多都是重復的,不...
摘要:今天我們來自己手寫一個符合規范的庫。是異步編程的一種解決方案,比傳統的解決方案回調函數和事件更合理和更強大。我們可以看到,其實就是一個構造函數。所以說我們的數組里存的是一個一個的的回調函數,也就是一個一個。 今天我們來自己手寫一個符合PromiseA+規范的Promise庫。大家是不是很激動呢?? showImg(https://segmentfault.com/img/bV6t4Z?...
摘要:如果實現滿足所有要求,則實現可能允許。本條款允許使用特定于實現的方法來采用已知一致承諾的狀態。接下來根據規范進行手寫實現注釋偷懶就將對應的規范標注出來,其實基本上就是對著規范實現。 如果要手寫實現promise,那么先看看promise/A+規范,再來實現,將會事半功倍。那么我先翻譯一下Promise/A+規范中的內容。 術語 1.1 promise 是一個帶有符合此規范的the...
摘要:構造函數的實現我們在使用的時候其實是使用關鍵字創建了一個的實例,其實是一個類,即構造函數,下面來實現構造函數。 showImg(https://segmentfault.com/img/remote/1460000018998456); 閱讀原文 概述 Promise 是 js 異步編程的一種解決方案,避免了 回調地獄 給編程帶來的麻煩,在 ES6 中成為了標準,這篇文章重點不是敘...
閱讀 2081·2021-11-02 14:48
閱讀 2759·2019-08-30 14:19
閱讀 2928·2019-08-30 13:19
閱讀 1296·2019-08-29 16:17
閱讀 3229·2019-08-26 14:05
閱讀 2985·2019-08-26 13:58
閱讀 3075·2019-08-23 18:10
閱讀 1102·2019-08-23 18:04