摘要:手寫一款符合規范的長篇預警有點長,可以選擇性觀看。初始狀態是,狀態可以有或者不能從轉換為或者從轉換成即只要由狀態轉換為其他狀態后,狀態就不可變更。
手寫一款符合Promise/A+規范的Promise
長篇預警!有點長,可以選擇性觀看。如果對Promise源碼不是很清楚,還是推薦從頭看,相信你認真從頭看到尾,并且去實際操作了,肯定會有收獲的。主要是代碼部分有點多,不過好多都是重復的,不必擔心
Promise的一些用法在此不多贅述,本篇主要帶領你手寫一個Promise源碼,學完你就會發現:Promise沒有你想象中的那么難
本篇大概分為以下步驟實現簡單的同步Promise
增加異步功能
增加鏈式調用then
增加catch finally方法
增加all race 等方法
實現一個promise的延遲對象defer
最終測試
實現簡單的同步Promise
先大概說一下基本概念:
Promise內部維護著三種狀態,即pending,resolved和rejected。初始狀態是pending,狀態可以有pending--->relolved,或者pending--->rejected.不能從resolve轉換為rejected 或者從rejected轉換成resolved.
即 只要Promise由pending狀態轉換為其他狀態后,狀態就不可變更。
ok.知道了這些后,我們開始手擼代碼:
注意觀看序號 1 2 3 4 5 ...
function Promise(executor){ let that = this; /** 2 定義初始的一些變量 */ that.status = "pending"; that.value = null; that.reason = null; /** 3 定義初始的成功和失敗函數 */ function resolve(value){ /** 4 判斷狀態是不是初始狀態pending * 是就轉換狀態 否則不轉換 * 確保狀態的變化后的不可變性 */ if(that.status === "pending"){ that.status = "resolved"; that.value = value; } } function reject(reason){ /** 5 同上 */ if(that.status === "pending"){ that.status = "rejected"; that.reason = reason; } } /** * 1 Promise中首先傳了一個executor,它是一個函數 * executor函數中又傳了兩個函數,分別是resolve和reject * 很顯然 resolve是成功回調,reject是失敗的回調 */ executor(resolve,reject); } /** 6 在Promise原型上面定義then方法 * then方法上面有兩個回調 一個是成功后的方法 另一個是失敗后的方法 * 根據成功或失敗的狀態去執行相關成功onFilfulled()或者失敗onRejected()的回調方法 */ Promise.prototype.then = function(onFilfulled,onRejected){ let that = this; if(that.status === "resolved"){ /** 7 如果狀態已經變更為resolved * 說明resolve方法已經被調用 * 那么此時就執行成功的回調函數onFilfulled * 并傳入參數 that.value * */ onFilfulled(that.value); } if(that.status === "rejected"){ /** 8 同上 * 傳入參數 that.reason */ onRejected(that.reason); } } module.exports = Promise;
通過require()引入手擼的Promise
let Promise = require("./myPromise"); let p1 = ()=>{ return new Promise((resolve,reject)=>{ resolve("success.1"); }); } p1().then((data)=>{ console.log(data); // 打印 success.1 },(err)=>{ console.log(err); });
ok.經調用發現 此代碼可以實現部分Promise的功能,但僅僅是同步下才有效果。
那異步呢? 別急這就來~:
增加異步功能
注意觀看序號 1 2 3 4 5 ...
function Promise(executor){ let that = this; that.status = "pending"; that.value = null; that.reason = null; /** 1 因為異步不是立即執行 狀態不會變更 成功或失敗的回調函數也不會執行 * 所以先定義好存放成功或失敗回調函數的數組 * 以便將成功或失敗的回調函數先保存起來 * */ that.onFilFulledCallbacks = []; that.onRejectedCallbacks = []; function resolve(value){ if(that.status === "pending"){ that.status = "resolved"; that.value = value; /** 3 發布 * 等待狀態發生變更 * 狀態變更后 立即執行之前存放在相應數組中所有的成功或失敗的回調函數 * 即 發布 */ that.onFilFulledCallbacks.forEach((fn)=>{ fn(); }); } } function reject(reason){ if(that.status === "pending"){ that.status = "rejected"; that.reason = reason; /** 4 同上 */ that.onRejectedCallbacks.forEach((fn)=>{ fn(); }); } } executor(resolve,reject); } Promise.prototype.then = function(onFilfulled,onRejected){ let that = this; if(that.status === "resolved"){ onFilfulled(that.value); } if(that.status === "rejected"){ onRejected(that.reason); } /** 2 訂閱 * 因為是異步 狀態當時并沒有立即變更 所以狀態還是pending * 此時需要把成功或者失敗的回調函數存放到對應的數組中 * 等待狀態變更時 再從數組中拿出來去執行 * 即 訂閱 * *存放數組時 為了執行時方便 需要把回調函數的外層包裹一層空函數 */ if(that.status === "pending"){ that.onFilFulledCallbacks.push(function(){ onFilfulled(that.value); }); } if(that.status === "pending"){ that.onRejectedCallbacks.push(function(){ onRejected(that.reason); }); } } module.exports = Promise;
代碼測試:
let Promise = require("./myPromise"); let p1 = ()=>{ return new Promise((resolve,reject)=>{ setTimeout(function(){ resolve("success.1"); // reject("fail."); },1500); }); } p1().then((data)=>{ console.log(data); // success.1 },(err)=>{ console.log(err); });
可以看到 1.5s后 執行了resolve() 并打印了success.1,至此,我們實現了異步的Promise.其實這里的實現異步的思想就是發布訂閱.
en~ok.高能預警
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101880.html
摘要:本文同時也發布在我的博客上,歡迎之前也手寫過簡單的,這次則是為了通過官方的測試集,借鑒了一些下載量較多的,改了幾遍,終于是通過了規范的個測試用例如何測試測試庫地址在這,大家在寫完自己的后,不妨也去測試一下,檢驗自己的是否符合規范。 本文同時也發布在我的github博客上,歡迎star~ 之前也手寫過簡單的promise,這次則是為了通過官方的Promise A+測試集,借鑒了一些下載量...
摘要:如果實現滿足所有要求,則實現可能允許。本條款允許使用特定于實現的方法來采用已知一致承諾的狀態。接下來根據規范進行手寫實現注釋偷懶就將對應的規范標注出來,其實基本上就是對著規范實現。 如果要手寫實現promise,那么先看看promise/A+規范,再來實現,將會事半功倍。那么我先翻譯一下Promise/A+規范中的內容。 術語 1.1 promise 是一個帶有符合此規范的the...
摘要:使用及原理分析通過關鍵字創建實例接受一個參數方法返回兩個方法可用通過在方法中通過調用使成功或調用使失敗來控制狀態中可以執行同步代碼也可以執行異步代碼原型對象上有方法供實例調用方法接受兩個參數默認為一個函數默認為一個函數當狀態為時執行用戶傳入 promise使用及原理分析: 通過new關鍵字創建promise實例, 接受一個executor參數, executor方法返回兩個方法 res...
摘要:構造函數的實現我們在使用的時候其實是使用關鍵字創建了一個的實例,其實是一個類,即構造函數,下面來實現構造函數。 showImg(https://segmentfault.com/img/remote/1460000018998456); 閱讀原文 概述 Promise 是 js 異步編程的一種解決方案,避免了 回調地獄 給編程帶來的麻煩,在 ES6 中成為了標準,這篇文章重點不是敘...
摘要:如果狀態是等待態的話,就往回調函數中函數,比如如下代碼就會進入等待態的邏輯以上就是簡單版實現實現一個符合規范的接下來大部分代碼都是根據規范去實現的。 為更好的理解, 推薦閱讀Promise/A+ 規范 實現一個簡易版 Promise 在完成符合 Promise/A+ 規范的代碼之前,我們可以先來實現一個簡易版 Promise,因為在面試中,如果你能實現出一個簡易版的 Promise ...
閱讀 3834·2021-09-27 13:56
閱讀 881·2021-09-08 09:36
閱讀 765·2019-08-30 15:54
閱讀 609·2019-08-29 17:29
閱讀 927·2019-08-29 17:21
閱讀 1683·2019-08-29 16:59
閱讀 2757·2019-08-29 13:03
閱讀 2964·2019-08-29 12:47