摘要:以下方式寫提示未定義涉及閉包作用域鏈的問題改進方式調用實例化回調函數執行成功,并執行函數,此時在回調隊列里面添加一一個函數,并將的參數傳遞出去。否則直接執行回調函數,不會由來觸發的回調函數執行。
function Promise(fn){ //需要一個成功時的回調 var self = this var callback; //一個實例的方法,用來注冊異步事件 self.then = function(done){ callback = done; } // resolve 比 then 先執行 此時 callback 不存在 // 所以 加一個 setTimeout 讓resolve 函數在回調隊列的末尾 // 為啥是0秒? 為啥處于回調隊列末尾? //(權威指南)如果以0毫秒的超時時間來調用setTimeout(),那么指定的函數不會立即執 // 行,相反會把它放到隊列中去,等到前面處于等待狀態的事件處理程序全部執行完成后, // 再“立即”調用它。 // 以下 方式寫 提示 resolve 未定義 涉及閉包 作用域鏈的問題 // setTimeout(function () { // function resolve(value){ // callback && callback(value); // } // }, 0) // 改進方式 function resolve (value) { setTimeout(function () { callback && callback(value) }, 0) } fn(resolve); }
調用promise
// 實例化promise 回調函數fn執行成功,并執行resolve函數,此時在回調隊列里面添加一 // 一個callback函數,并將resolve的參數傳遞出去。 var promise = new Promise(function (resolve) { resolve(["3", "aaa"]) }) // 調用then函數,并執行then回調,將then函數的參數done回調函數賦值給callback, // 在回調隊列里面(之前setTimeout添加進去的回調隊列)執行then的回調函數 promise.then(function (data) { console.log("data", data) })
但是以上方式寫,我們永遠都只能執行then中一個回調隊列,這顯然不健壯。我們結合js設計模式的發布--消息訂閱模式,再結合構造函數return this 知識點,稍微改造下:
function Promise(fn){ //需要一個成功時的回調 var self = this self.deferreds = []; // then函數 回調隊列 儲存容器 //一個實例的方法,用來注冊異步事件 self.then = function(onFulfilled){ self.deferreds.push(onFulfilled) console.log("self.deferreds", self.deferreds) // 調用兩次then 回調隊列會逐個push return self // 鏈式調用then } // 改進方式 function resolve (value) { setTimeout(function () { self.deferreds.forEach(function (deferred) { deferred && deferred(value) }) }, 0) } fn(resolve); }
調用then函數:
promise.then(function (data) { console.log("data", data) }).then(function (resp) { console.log("resp", resp) })
眾所周知,構造函數Promise存在三個互斥狀態:pending、fulfilled、rejected。Promise 對象的狀態改變,只有兩種可能:從 pending 變為 fulfilled 和從 pending 變為 rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果。
所以:我們改進代碼如下:
//略 // 初始化設置狀態 self.status = "pending" //略 // ... //略 // resolve的時候 將狀態置為 self.status = "fulfilled" //略
調用執行,同樣可以得到我們想要的數據。
但是
但是
但是
僅僅加上上面兩行代碼是不行的,仔細理解加粗的那幾個字,再結合我們的代碼來看。
當我們調用then函數的時候,往我們then回調隊列里面push回調函數,最終不管狀態是pending
還是fulfilled,回調隊列的函數都是被resolve函數觸發的。這樣就違背了這句話:只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果。
當我們狀態改變為fulfilled,我們并沒有真正改變狀態,每次再重新執行的時候,我們又重新走了一次then添加回調,然后由resolve來觸發回調的過程。
所以then函數改進代碼如下:
// 當status == "pending"的時候,我們才往then的回調隊列push回調函數。 // 否則 直接執行回調函數,不會由resolve來觸發then的回調函數執行。 if(self.status == "pending") { self.deferreds.push(onFulfilled) return self } onFulfilled(value) return self // 鏈式調用then
所以加入value后,最終代碼如下:
基本就實現了鏈式調用then的一個帶有pending 和 fulfilled 狀態的Promise
后續會加上reject(), rejected以及最難理解的串行promise。
function Promise(fn){ //需要一個成功時的回調 var self = this self.deferreds = []; // then函數 回調隊列 儲存容器 self.status = "pending" self.value = null //一個實例的方法,用來注冊異步事件 self.then = function(onFulfilled){ if(self.status == "pending") { self.deferreds.push(onFulfilled) return self } onFulfilled(self.value) return self // 鏈式調用then } // 改進方式 function resolve (newValue) { setTimeout(function () { self.value = newValue self.status = "fulfilled" self.deferreds.forEach(function (deferred) { deferred && deferred(self.value) }) }, 0) } fn(resolve); }附錄參考文獻
美團點評
cn博客
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107055.html
摘要:接下來我們看下三類異步編程的實現。事件監聽事件發布訂閱事件監聽是一種非常常見的異步編程模式,它是一種典型的邏輯分離方式,對代碼解耦很有用處。 一、 一道面試題 前段時間面試,考察比較多的是js異步編程方面的相關知識點,如今,正好輪到自己分享技術,所以想把js異步編程學習下,做個總結。下面這個demo 概括了大多數面試過程中遇到的問題: for(var i = 0; i < 3; i++...
摘要:鏈式是指在當前達到狀態后,即開始進行下一個后鄰。在中發現沒有指定異步操作失敗的回調時,會直接將函數返回的,后同設為狀態,如此達成執行后續失敗回調的效果。 原文鏈接 前言 前一陣子記錄了promise的一些常規用法,這篇文章再深入一個層次,來分析分析promise的這種規則機制是如何實現的。ps:本文適合已經對promise的用法有所了解的人閱讀,如果對其用法還不是太了解,可以移步我的上...
摘要:意味著代指的操作由于某些原因失敗。第一步構造函數有三種狀態,。這個構造函數我們可以先這樣寫創建一個時,首先進行狀態初始化。所有的都是的,而并不是所有的對象都是。 一、JavaScript異步編程背景 ? 從去年ES2015發布至今,已經過去了一年多,ES2015發布的新的語言特性中最為流行的也就莫過于Promise了,Promise使得如今JavaScript異步編程如此輕松愜意...
摘要:原理分析一對象用于異步計算。它有兩個參數,分別為在成功和失敗情況下的回調函數。實現根據當前狀態對回調函數進行處理,同時返回一個新的對象,以便鏈式調用。,注冊回調函數到當前的對象中或,立即執行回調函數說明方法只處理被拒絕的情況,并返回一個。 Promise原理分析一 Promise對象用于異步計算。一個Promise對象代表著一個還未完成,但預期將來會完成的操作。 Note: Promi...
摘要:寫在前面使用框架開發時,很多人會選擇官方提供的腳手架,最新的已經更新到完全無配置,只需下載就能方便的使用構建的項目工程,但基礎的并不能滿足正常的項目開發,在開發中我們需要根據自己的習慣和業務功能而添加些基礎功能。 寫在前面 使用vue框架開發時,很多人會選擇vue官方提供的cli腳手架,最新的cli已經更新到3.0完全無配置,只需下載就能方便的使用vuecli構建的項目工程,但基礎的c...
閱讀 2225·2021-09-22 15:25
閱讀 3610·2019-08-30 12:48
閱讀 2197·2019-08-30 11:25
閱讀 2332·2019-08-30 11:05
閱讀 720·2019-08-29 17:28
閱讀 3279·2019-08-26 12:16
閱讀 2602·2019-08-26 11:31
閱讀 1683·2019-08-23 17:08