摘要:使用及原理分析通過(guò)關(guān)鍵字創(chuàng)建實(shí)例接受一個(gè)參數(shù)方法返回兩個(gè)方法可用通過(guò)在方法中通過(guò)調(diào)用使成功或調(diào)用使失敗來(lái)控制狀態(tài)中可以執(zhí)行同步代碼也可以執(zhí)行異步代碼原型對(duì)象上有方法供實(shí)例調(diào)用方法接受兩個(gè)參數(shù)默認(rèn)為一個(gè)函數(shù)默認(rèn)為一個(gè)函數(shù)當(dāng)狀態(tài)為時(shí)執(zhí)行用戶傳入
promise使用及原理分析:
通過(guò)new關(guān)鍵字創(chuàng)建promise實(shí)例, 接受一個(gè)executor參數(shù), executor方法返回兩個(gè)方法 resolve, reject, 可用通過(guò)在executor方法中通過(guò)調(diào)用resolve(使成功)或調(diào)用reject(使失敗),來(lái)控制promise狀態(tài)
let p = new Promise((resolve, reject) => { resolve(100) })
executor中可以執(zhí)行同步代碼也可以執(zhí)行異步代碼
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve(100) }) })
promise原型對(duì)象上有then方法供promise實(shí)例調(diào)用, then方法接受兩個(gè)參數(shù)onFulfilled, onRejected
onFulfilled默認(rèn)為一個(gè)函數(shù) data => data
onRejected默認(rèn)為一個(gè)函數(shù) err => {throw err}
當(dāng)promise狀態(tài)為fulfilled時(shí), 執(zhí)行用戶傳入的onFulfilled方法
當(dāng)promise狀態(tài)為rejected時(shí), 執(zhí)行用戶傳入的onRected方法
當(dāng)用戶創(chuàng)建promise對(duì)象時(shí)采用異步,那么執(zhí)行then方法時(shí)沒(méi)有調(diào)用resolve方法或reject方法,所以promise狀態(tài)依然為pending狀態(tài),所以需要在then方法中采取發(fā)布訂閱模式,先保存then方法傳來(lái)的onFulfilled和onReje
又因?yàn)橥粋€(gè)promise實(shí)例可以調(diào)用多次then方法,從而傳多個(gè)onFulfilled和onRected,所以發(fā)布訂閱采用數(shù)組保存
onFulfilled和onRejected方法中可能throw Error, 所以在執(zhí)行onFulfilled和onRejected時(shí)需要try catch捕獲
then方法返回一個(gè)新的Promise實(shí)現(xiàn)鏈?zhǔn)骄幊?/p>
統(tǒng)一判斷then方法傳入的onFulfilled方法和onRejected方法中return的類型(resolvePromise)
p.then(data => { console.log(data) }, err => { console.log(err) })
let p1 = p.then(data => { return p1 // 報(bào)類型錯(cuò)誤 })
p.then(data => { return new Promise((resolve, reject) => { resolve(100) }) })
catch方法接受一個(gè)錯(cuò)誤回調(diào),可以用then方法實(shí)現(xiàn)(語(yǔ)法糖)
ES2018 中新增finally方法 也可以通過(guò)then方法實(shí)現(xiàn)(語(yǔ)法糖) finally要實(shí)現(xiàn)值得穿透, finally前如果有then方法,其返回值要穿過(guò)finally方法傳給之后的then
p.then(data => { return 100 }).finally(() => { console.log("finally") }).then(data => { console.log(data) // 100 })
all, race 方法都接受一個(gè)promise數(shù)組
all方法要所有promise都返回才resolve一個(gè)全部是成功態(tài)的數(shù)組,只要有一個(gè)rejected就直接reject
race方法只要有一個(gè)promise resolve就直接resolve
完整代碼如下:class Promise { constructor(executor) { this.status = Promise.PENDING this.value = undefined this.reason = undefined // 發(fā)布訂閱的存儲(chǔ)器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中拋錯(cuò) try { executor(this.resolve, this.reject) } catch (e) { this.reject(e) } } resolve(data) { // 如果resolve中傳入一個(gè)promise, 那么返回改promise結(jié)果 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定義默認(rèn)值 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) }) } }) // 返回一個(gè)新的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即執(zhí)行resolve又執(zhí)行 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 // 遞歸解析,總有一個(gè)結(jié)果then方法返回一個(gè)普通值 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" } // 延遲對(duì)象 Promise.deferred = () => { const defer = {} defer.promise = new Promise((resolve, reject) => { defer.resolve = resolve defer.reject = reject }) return defer } module.exports = Promise
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104774.html
摘要:本文同時(shí)也發(fā)布在我的博客上,歡迎之前也手寫(xiě)過(guò)簡(jiǎn)單的,這次則是為了通過(guò)官方的測(cè)試集,借鑒了一些下載量較多的,改了幾遍,終于是通過(guò)了規(guī)范的個(gè)測(cè)試用例如何測(cè)試測(cè)試庫(kù)地址在這,大家在寫(xiě)完自己的后,不妨也去測(cè)試一下,檢驗(yàn)自己的是否符合規(guī)范。 本文同時(shí)也發(fā)布在我的github博客上,歡迎star~ 之前也手寫(xiě)過(guò)簡(jiǎn)單的promise,這次則是為了通過(guò)官方的Promise A+測(cè)試集,借鑒了一些下載量...
摘要:手寫(xiě)一款符合規(guī)范的長(zhǎng)篇預(yù)警有點(diǎn)長(zhǎng),可以選擇性觀看。初始狀態(tài)是,狀態(tài)可以有或者不能從轉(zhuǎn)換為或者從轉(zhuǎn)換成即只要由狀態(tài)轉(zhuǎn)換為其他狀態(tài)后,狀態(tài)就不可變更。 手寫(xiě)一款符合Promise/A+規(guī)范的Promise 長(zhǎng)篇預(yù)警!有點(diǎn)長(zhǎng),可以選擇性觀看。如果對(duì)Promise源碼不是很清楚,還是推薦從頭看,相信你認(rèn)真從頭看到尾,并且去實(shí)際操作了,肯定會(huì)有收獲的。主要是代碼部分有點(diǎn)多,不過(guò)好多都是重復(fù)的,不...
摘要:今天我們來(lái)自己手寫(xiě)一個(gè)符合規(guī)范的庫(kù)。是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大。我們可以看到,其實(shí)就是一個(gè)構(gòu)造函數(shù)。所以說(shuō)我們的數(shù)組里存的是一個(gè)一個(gè)的的回調(diào)函數(shù),也就是一個(gè)一個(gè)。 今天我們來(lái)自己手寫(xiě)一個(gè)符合PromiseA+規(guī)范的Promise庫(kù)。大家是不是很激動(dòng)呢?? showImg(https://segmentfault.com/img/bV6t4Z?...
摘要:如果實(shí)現(xiàn)滿足所有要求,則實(shí)現(xiàn)可能允許。本條款允許使用特定于實(shí)現(xiàn)的方法來(lái)采用已知一致承諾的狀態(tài)。接下來(lái)根據(jù)規(guī)范進(jìn)行手寫(xiě)實(shí)現(xiàn)注釋偷懶就將對(duì)應(yīng)的規(guī)范標(biāo)注出來(lái),其實(shí)基本上就是對(duì)著規(guī)范實(shí)現(xiàn)。 如果要手寫(xiě)實(shí)現(xiàn)promise,那么先看看promise/A+規(guī)范,再來(lái)實(shí)現(xiàn),將會(huì)事半功倍。那么我先翻譯一下Promise/A+規(guī)范中的內(nèi)容。 術(shù)語(yǔ) 1.1 promise 是一個(gè)帶有符合此規(guī)范的the...
摘要:構(gòu)造函數(shù)的實(shí)現(xiàn)我們?cè)谑褂玫臅r(shí)候其實(shí)是使用關(guān)鍵字創(chuàng)建了一個(gè)的實(shí)例,其實(shí)是一個(gè)類,即構(gòu)造函數(shù),下面來(lái)實(shí)現(xiàn)構(gòu)造函數(shù)。 showImg(https://segmentfault.com/img/remote/1460000018998456); 閱讀原文 概述 Promise 是 js 異步編程的一種解決方案,避免了 回調(diào)地獄 給編程帶來(lái)的麻煩,在 ES6 中成為了標(biāo)準(zhǔn),這篇文章重點(diǎn)不是敘...
閱讀 2094·2021-11-02 14:48
閱讀 2771·2019-08-30 14:19
閱讀 2939·2019-08-30 13:19
閱讀 1306·2019-08-29 16:17
閱讀 3244·2019-08-26 14:05
閱讀 2997·2019-08-26 13:58
閱讀 3086·2019-08-23 18:10
閱讀 1112·2019-08-23 18:04