摘要:如果讓你實現一個你會怎么做自己實現的大體思路我們要明確我們需要一個異步的操作方法滿足異步回調。所以選擇加入作為實現的基礎,讓函數實現延遲觸發。測試代碼測試第二版實現返回一個觸發返回一個觸發
如果讓你實現一個 promise ,你會怎么做? 自己實現promise的大體思路
我們要明確我們需要一個異步的操作方法,滿足異步回調。所以選擇加入setTimeout 作為實現的基礎, 讓函數實現延遲觸發。
保持一個原則,控制 promise 改變狀態的只有 promise 構造函數里的 reslove 、 reject 函數。
鏈式調用的原理, 類似jQuery,它會在調用方法后, return this. 從而形成鏈式調用。所以我們采用在調用then(fn)、 catch(fn) 后 會返回一個新的 promise 對象, 然而 這個 promise 對象 受到 它的上級promise 對象的狀態結果 和 fn 運行結果的控制。
知識點:
里面 應該 用到點 js 作用域 、 函數閉包、 繼承 、 上下文 綁定知識、引用傳遞。
cbList、rhList、 cs 這個三個, Promise 對象能直接訪問, 如果對其直接操作可能造成 程序紊亂。
代碼如有紕漏,望大家指正
var JcPromise = function (fn) { // 防止 用戶 直接 更改 state var state = "wait" // state 為 resolve 狀態, 回調函數數組 var cbList = [] // state 為 reject 狀態, 回調函數數組 var rjList = [] this.cbList = cbList this.rjList = rjList // this.cs = undefined // 獲取 promise 的狀態 this.getState = function () { return state } /* 函數閉包,函數 定義在里面, 防止 外面用戶 直接 使用 resolve 和 reject; */ // Promise成功觸發 函數 var reslove = function (data) { this.cs = data if (state !== "wait") { return } else { state = "solve" while (this.cbList.length) { cbList.shift()(data) } } } // Promise 拒絕 觸發函數 var reject = function (e) { this.cs = e if (state !== "wait") { return } else { state = "reject" while (rjList.length) { rjList.shift()(e) } } } // 綁定函數 conext 及 this 為當前 promise對象 reslove = reslove.bind(this) reject = reject.bind(this) // 延遲 觸發 setTimeout(function () { fn(reslove, reject) }, 0) } JcPromise.prototype.then = function (fn) { var handleObj = {} var nextPromise = new JcPromise(function (r, j) { handleObj.r = r handleObj.j = j }) var fixFn = function (data) { var result = null try { result = fn(data) // 判斷result是不是 JcPromise實例。 if (result instanceof JcPromise) { result.then(function (data) { handleObj.r(data) }).catch(function (e) { handleObj.j(e) }) } else { handleObj.r(result) } } catch (e){ handleObj.j(e) } } //判斷當前狀態 如果 是 solve 直接 運行, 如果不是,酒吧 fixFn 推入 cbList 數組。 if (this.getState() === "solve") { setTimeout(function () { fixFn(this.cs) }, 0) } else { this.cbList.push(fixFn) } return nextPromise } JcPromise.prototype.catch = function (fn) { var handleObj = {} var nextPromise = new JcPromise(function (r, j) { handleObj.r = r handleObj.j = j }) var fixFn = function (e) { var result = null try { result = fn(e) if (result instanceof JcPromise) { result.then(function (data) { handleObj.r(data) }).catch(function (e) { handleObj.j(e) }) } else { handleObj.r(result) } } catch (e){ handleObj.j(e) } } if (this.getState() === "reject") { setTimeout(function () { fixFn(this.cs) }, 0) } else { this.rjList.push(fixFn) } return nextPromise }
// 測試代碼 var p = new JcPromise(function(r, j) { setTimeout(function() {r(100)}, 3000) }).then(data => { console.log("1", data) return new JcPromise((r, j) => { setTimeout(() => { r("hi") }, 3000) }) }).then(data => console.log("2", data)).then(function () { console.log("xxx", xx + 1) }).catch(e => console.log(e)).then(data => console.log(data, "end"))
demo 測試
第二版 jcPromise 實現
var JcPromise = (function() { function JcPromise(fn) { fn = fn || noop; var statusList = ["start", "pending", "succeed", "err"]; var cbStatus = [0, 1]; var status = statusList[0]; var data = null; var err = null; var that = this; var successFn = []; var errFn = []; function resolve(d) { data = d; that._changeStatus(2); }; function reject(e) { err = e; that._changeStatus(3); }; this.getData = function() { return data; }; this.getErr = function() { return err }; this.getStatus = function() { return status }; this._changeStatus = function(idx) { switch (status) { case statusList[2]: case statusList[3]: { return false } }; status = statusList[idx]; if (status === statusList[3]) { setTimeout(function() { that._triggerCatch(); }, 0) } if (status === statusList[2]) { setTimeout(function() { that._triggerThen(); }, 0) } }; this._pushThenCb = function(cb) { successFn.push({ status: cbStatus[0], cb: cb }); if (status === statusList[2]) { this._triggerThen(); } }; this._pushCatchCb = function(cb) { errFn.push({ status: cbStatus[0], cb: cb }); if (status === statusList[3]) { this._triggerCatch(); } }; this._triggerThen = function() { successFn.map(function(item) { if (item.status === cbStatus[0]) { item.cb(data); item.status = cbStatus[1]; } }) }; this._triggerCatch = function() { errFn.map(function(item) { if (item.status === cbStatus[0]) { item.cb(err); item.status = cbStatus[1]; } }) }; this._changeStatus(1); this.uuid = uuid++; try { fn(resolve, reject); } catch (e) { reject(e) } return this }; JcPromise.fn = JcPromise.prototype; // 返回一個promise JcPromise.fn.then = function(cb) { var promiseR = null; var promiseJ = null; var result = null; var that = this; var fn = function() { setTimeout(function() { try { var data = that.getData(); result = cb(data); if (typeof result === "object" && result !== null && result.constructor === JcPromise) { result.then(function(data) { promiseR(data) }).catch(function(e) { promiseJ(e) }) } else { promiseR(result) } } catch (e) { promiseJ(e) } }, 0); }; this._pushThenCb(fn); // 觸發promise return new JcPromise(function(r, j) { promiseR = r; promiseJ = j; }); }; // 返回一個promise JcPromise.fn.catch = function(cb) { var promiseR = null; var promiseJ = null; var result = null; var that = this; var fn = function() { setTimeout(function() { try { var data = that.getErr(); result = cb(data); if (typeof result === "object" && result !== null && result.constructor === JcPromise) { result.then(function(data) { promiseR(data) }).catch(function(e) { promiseJ(e) }) } else { promiseR(result) } } catch (e) { promiseJ(e) } }, 0) }; this._pushCatchCb(fn); // 觸發promise return new JcPromise(function(r, j) { promiseR = r; promiseJ = j; }); }; return JcPromise })();
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93453.html
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規范并可配合使用的寫一個符合規范并可配合使用的理解的工作原理采用回調函數來處理異步編程。 JavaScript怎么使用循環代替(異步)遞歸 問題描述 在開發過程中,遇到一個需求:在系統初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...
摘要:面試題來源于網絡,看一下高級前端的面試題,可以知道自己和高級前端的差距。 面試題來源于網絡,看一下高級前端的面試題,可以知道自己和高級前端的差距。有些面試題會重復。 使用過的koa2中間件 koa-body原理 介紹自己寫過的中間件 有沒有涉及到Cluster 介紹pm2 master掛了的話pm2怎么處理 如何和MySQL進行通信 React聲明周期及自己的理解 如何...
摘要:面試的公司分別是阿里網易滴滴今日頭條有贊挖財滬江餓了么攜程喜馬拉雅兌吧微醫寺庫寶寶樹??低暷⒐浇挚峒覙钒俜贮c和海風教育。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本人于7-8月開始準備面試,過五關斬六將,最終抱得網易歸,深深感受到高級前端面試的套路。以下是自己整理的面試題匯總,不敢藏私,統統貢獻出來。 面試的公司分...
閱讀 2234·2021-11-16 11:44
閱讀 641·2019-08-30 15:55
閱讀 3271·2019-08-30 15:52
閱讀 3595·2019-08-30 15:43
閱讀 2196·2019-08-30 11:21
閱讀 435·2019-08-29 12:18
閱讀 1945·2019-08-26 18:15
閱讀 468·2019-08-26 10:32