日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Promise-Polyfill源码解析(2)

發布時間:2025/3/8 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Promise-Polyfill源码解析(2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在上篇文章Promise-Polyfill源碼解析(1)詳細分析了Promise構造函數部分的源碼,本篇我們繼續分析剩下的源碼。 本篇我們重點分析then方法,讓我們回憶下then方法的使用方式:首先這個方法屬于每個Promise對象,這說明then方法應該定義在Promise的原型鏈上;然后這個方法接收兩個回調函數,如果Promsie的狀態為已完成,則執行第一個回調,狀態為被拒絕,則執行第二個回調,這個說明then方法會等待Promise狀態改變才會去執行回調;最后then方法可以鏈式調用,如下:

Promise.resolve().then(function() {// ... }, function() {// ... }).then(function() {// ... }, function() {// ... }); 復制代碼

了解了以上,我們來看then方法的源碼:

Promise.prototype.then = function(onFulfilled, onRejected) {// @ts-ignorevar prom = new this.constructor(noop);handle(this, new Handler(onFulfilled, onRejected, prom));return prom; }; 復制代碼

正如我們所猜想的,then方法定義在Promise的構造函數上,每個Promise對象可以共享該方法。其接收兩個參數onFulfilled、onRejected。具體實現也非常簡潔,只有三行代碼,先來看第一行:

var prom = new this.constructor(noop); 復制代碼

這句代碼用new操作符實例化了一個對象,并保存在prom變量中。new操作符的右邊一定是個構造函數,this指向當前Promise對象,其constructor屬性指向構造函數,所以this.constructor指向Promise構造函數。我們知道,Promise構造函數的參數為一個函數,這里傳入了noop,noop是什么?我們找到其定義:

function noop() {} 復制代碼

我們發現noop只是個空函數。再來看最后一行代碼:

return prom; 復制代碼

返回了prom對象,也就是說,then方法最后返回了一個Promise對象,這也就是then方法可以鏈式調用的原因所在! 有個疑問,為什么不直接返回this,而是返回新創建的Promise對象呢?其實是因為Promise的狀態改變時單向的,且只能改變一次。 然后重點來看下第二行代碼:

handle(this, new Handler(onFulfilled, onRejected, prom)); 復制代碼

調用了handle函數,先不管handle做了什么,我們先關注其第二個實參:

new Handler(onFulfilled, onRejected, prom) 復制代碼

其實例化了Handler對象,參數為then方法的兩個參數和prom對象,我們來看下其具體實現:

/*** @constructor*/ function Handler(onFulfilled, onRejected, promise) {this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;this.onRejected = typeof onRejected === 'function' ? onRejected : null;this.promise = promise; } 復制代碼

Handler構造函數將傳入的參數分別賦值給實例對象的onFulfilled、onRejected、promise屬性,其中對onFulfilled和onRejected做了處理,若不是函數類型,則賦值為null。這說明,我們傳入給then方法的兩個參數可以不為函數類型,其內部會調整為null。 明白了第二個參數,我們來看handle函數具體做了什么:

function handle(self, deferred) {while (self._state === 3) {self = self._value;}if (self._state === 0) {self._deferreds.push(deferred);return;}self._handled = true;Promise._immediateFn(function() {var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;if (cb === null) {(self._state === 1 ? resolve : reject)(deferred.promise, self._value);return;}var ret;try {ret = cb(self._value);} catch (e) {reject(deferred.promise, e);return;}resolve(deferred.promise, ret);}); } 復制代碼

首先是一個while循環:

while (self._state === 3) {self = self._value;} 復制代碼

self指的是當前Promise對象,如果self._state的值為3,則將self._value賦值給self。我們在上篇文章分析過,_state屬性值為3,則說明_value值為一個Promise對象。那么這個循環的結果就是,直到_value屬性值不為Promise對象,為什么要這么處理呢?我們來看下規范是怎么說的: 如果 x 為 Promise,則使promise接收x的狀態

  • 如果 x 處于pendding,promise需要保持為pendding狀態直至x被解決或拒絕
  • 如果 x 處于fulFilled,用相同的值執行 promise
  • 如果 x 處于rejected,用相同的據因拒絕 promise 總結起來就是,如果_value屬性值為Promise對象,則結果取決于嵌套最內層Promise的狀態。 接下來是一個條件判斷:
if (self._state === 0) {self._deferreds.push(deferred);return;} 復制代碼

如果self._state屬性為0,則將deferred壓入self._deferreds數組,并結束此次函數調用。其中deferred為傳入的Handler實例對象,我們在上篇里分析過,_state屬性值為0表示Promise的狀態為pendding,我們可以猜測到,狀態為pedding,也就是Promise的狀態并未改變,then方法不知道要執行哪個回調,所在要先保存。那么為什么是保存在一個數組里,而不是保存在一個變量里,難道有很多個?其實還真可能有很多個,因為then方法可以被多次調用:

可以看到,每個then方法的回調都被執行了。 再來看下面的代碼:

self._handled = true; 復制代碼

上篇文章也分析過,_handled屬性用來標記Promise是否被處理,這里將其賦值為true,說明當前Promise對象已經被處理了。 最后來看最后一段代碼:

Promise._immediateFn(function() {... }); 復制代碼

調用了Promise._immediateFn方法,并傳入了一個回調函數。先來看Promise._immediateFn的定義:

// Use polyfill for setImmediate for performance gains Promise._immediateFn =(typeof setImmediate === 'function' &&function(fn) {setImmediate(fn);}) ||function(fn) {setTimeoutFunc(fn, 0);}; 復制代碼

這里判斷setImmediate是否是函數類型,成里則賦值為function(fn) { setImmediate(fn) },否則賦值為function(fn) { setTimeoutFunc(fn, 0) },其中setTimeoutFunc是setTimeout的別名:

var setTimeoutFunc = setTimeout; 復制代碼

setImmediate是Node.js里的global對象的屬性,而setTimeout是瀏覽器環境里window對象的屬性,所以Promise._immediate是兼容兩個環境所做處理的代碼。為什么要再包一層閉包呢?應該是兼容參數的數量。 到這我們也明白了,then方法的回調是異步執行,其實更具體是在micro隊列中,這里我們就不展開了。 回到Promise._immediateFn的回調參數:

var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; 復制代碼

上篇文章分析過,self._state屬性值為1表示Promise的狀態為已完成,為2表示狀態為被決絕。那么這句代碼的意思是,根據Promise的狀態,將then方法的完成回調或決絕回調賦值給cb變量。 再來看下面的條件判斷:

if (cb === null) {(self._state === 1 ? resolve : reject)(deferred.promise, self._value);return; } 復制代碼

cb變量為null,也就是我們傳入給then方法的參數不是函數類型,這里會根據Promise的狀態執行resolve或reject函數,并結束此次調用。注意傳入的參數,deferred.promise和self._value,也就是說,用Promise的值去改變在then方法內創建的Promise對象的狀態。總結起來就是,若then方法未傳入對應的回調,那么Promise的值會被傳遞到下一次then方法中:

再來看最后一段代碼:

var ret; try {ret = cb(self._value); } catch (e) {reject(deferred.promise, e);return; } resolve(deferred.promise, ret); 復制代碼

忽略try..catch,核心是這樣的:

var ret = cb(self._value); resolve(deferred.promise, ret); 復制代碼

將self._value作為參數,調用cb函數,返回值保存在ret變量中,再以ret變量為參數調用resolve函數。這里的意思就是,將cb函數的返回值作為Promise的值傳遞給下一個then方法:

當然,若拋出異常,則將原因作為Promise的值,傳遞給下一個then方法:

reject(deferred.promise, e); return; 復制代碼

至此,Promise源碼的核心部分已經分析完了,我們可以發現,閱讀源碼可以了解Promise的內部的工作機制,當出現問題時,我們也能快速定位原因。鼓勵大家去閱讀源碼! 當然還有catch、all、race等方法,將在下一篇文章繼續分析。

總結

以上是生活随笔為你收集整理的Promise-Polyfill源码解析(2)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲一二区视频 | 毛片在线免费 | 综合精品一区 | 日韩在线中文 | 亚洲av无码久久精品狠狠爱浪潮 | 夜夜草网站 | 97超碰人| 亚洲超碰av| 麻豆国产一区二区 | 亚洲精品自拍 | 狠狠撸在线观看 | 欧美成年人在线观看 | 美女福利片 | 欧美日韩69| 国产6区| 九九99精品 | 亚洲一区二区精品在线 | 天天干天天天 | 中国色老太hd| 久久精品牌麻豆国产大山 | 国产尤物av| 在线国产网站 | 俄罗斯丰满熟妇hd | 欧美极品在线播放 | 在线看片中文字幕 | 欧美二级片 | 人人澡超碰碰 | av鲁丝一区鲁丝二区鲁丝 | 我把护士日出水了视频90分钟 | 午夜综合网 | 五月激情五月婷婷 | 免费激情小视频 | 国产性色视频 | 1区2区3区在线观看 久久久久久久久久久影院 成人网址在线观看 | 美女露出让男生揉的视频 | 国产精品精品 | 伦理片波多野结衣 | 原创真实夫妻啪啪av | 精品久久久久久久久久岛国gif | 青青草公开视频 | 久久综合色网 | 国产做受91 | 午夜免费影院 | 伊人网在线 | 超碰黑人 | 午夜在线你懂的 | 中文字幕一区在线播放 | 国产一二三级 | 美女少妇av| 日韩熟女精品一区二区三区 | 波多野吉衣一二三区乱码 | 最新日本中文字幕 | 色欲av无码一区二区三区 | aaaa黄色 | 老汉av网站| 大胸奶汁乳流奶水出来h | 色噜噜综合 | 91网在线观看 | www国产亚洲精品久久网站 | 男女无套免费视频网站动漫 | 妹子色综合 | 日本白嫩的bbw | 欧美人妻精品一区二区免费看 | 久草播放 | 秋霞av在线 | 99热热热| 国产三级91 | 久久久久久精 | 国产在线视视频有精品 | 一区二区视频 | 碧蓝之海动漫在线观看免费高清 | 国产成人77亚洲精品www | 理论片琪琪午夜电影 | 五月婷婷操 | 91精品国产闺蜜国产在线闺蜜 | 黑帮大佬和我的365日第二部 | 日韩电影在线观看中文字幕 | 懂色av蜜臀av粉嫩av分享吧最新章节 | 亚洲av无码一区二区三区性色 | 国产日韩高清在线 | 久久99精品波多结衣一区 | 中文字字幕在线中文乱码 | 久久久久久香蕉 | 自拍偷拍国产 | 红猫大本营在线观看的 | 欧美美女色图 | 色视屏 | 亚洲人成影视 | 奇米影视久久久 | 公侵犯一区二区三区四区中文字幕 | 一级日韩一级欧美 | 成年视频在线观看 | 蜜臀久久99精品久久久画质超高清 | 日韩电影二区 | 亚洲自拍偷拍视频 | 97影院手机版 | 两根大肉大捧一进一出好爽视频 | 黄色香港三级三级三级 | 欧美天堂在线视频 |