javascript
javascript --- 手写Promise、快排、冒泡、单例模式+观察者模式
手寫promise
一種異步的解決方案, 參考
Promise代碼基本結構
function Promise(executor){this.state = 'pending';this.value = undefined;this.reason = undefined;function resolve(){}function reject(){} } module.exports = Promisestate保存的是當前的狀態,在Promise狀態發展只有以下兩種模式且不可逆:
pending - 等待態resolved - 成功態rejected - 失敗態從上可知,狀態只能由pending變為resolved(執行resolve)或pending變為rejected(執行reject)
這就引出了resolve和reject的功能
function Promise(executor){this.state = 'pending'this.value = undefinedthis.reason = undefinedfunction resolve(value){this.state = 'resolved'this.value = value}function reject(reason){this.state = 'rejected'this.reason = reason}executor(resove, reject) }then方法的實現
當Promise的狀態發生了改變,不論是成功或是失敗都會調用then方法
let p = new Promise((resolve, reject)=>{setTimeout(()=>{resolve(1)},50) }) p.then(data=>{console.log(data)})可以得出then的方法,由于then方法是每個實例所以共有,因此可以將其寫在原型鏈上:
- 接受2個參數,成功的回調onFulfilled和onRejected
- 兩個函數分別在resolved狀態下和rejected狀態下執行
當你寫出了以上的代碼,在同步的情況下執行完全沒有問題. 但是在異步的情況下,流程如下:
- 函數執行new Promise,當遇到setTimeout時,會將其推入一個異步隊列中
- 然后執行p.then: 瀏覽器會順著原型鏈找到Promise.prototype.then發現此時的狀態是pending,故不做任何處理,結束同步處理
- 開始執行異步隊列里面的setTimeout,執行resovle(1).
異步方法的實現
處理異步方法的關鍵是,在Promise.prototype.then方法中,當狀態為pending時,可以將處理函數作為變量存儲起來,這樣當異步過后,執行resolve時,可以在內存中找到相應的處理函數并對其進行執行.
這就需要我們修改Promise構造函數
function Promise(exector){this.state = 'pending'this.value = undefinedthis.reason = undefinedthis.onResolvedCallbacks = [] // 用于存儲成功的回調this.onRejectedCallbacks = [] // 用于存儲失敗的回調function resolve(value){if(this.state === 'pending'){this.state = 'resolved'this.value = valuethis.onResolvedCallbacks.forEach(resolved=> resolved(value))}}function reject(reason){if(this.state === 'pending'){this.state = 'rejected'this.reason = reasonthis.onRejectedCallbacks.forEach(rejected=> rejected(reason))}} }// 修改 Promise.prototype.then Promise.prototype.then = function (onFulfilled, onRejected){if(this.state === 'resolved'){onFulFilled(this.value)}if(this.state === 'rejected'){onRejected(this.reason)}// 異步: 將回調函數放入內存中.if(this.state === 'pending'){ if(typeof onFulfilled === 'function'){this.onResolvedCallbacks.push(onFulfilled)}if(typeof onRejected === 'function'){this.onRejectedCallbacks.push(onRejected)}} }當涉及到異步,使用this時要絕對小心
在使用setTimeout,里面回調使用的函數中的this是指向window的(通過debugger調試可以獲得).這就需要在一開始時,將指向實例的this保存下來.
function Promise(exector){let _this = this_this.state = 'pending'_this.value = undefined_this.reason = undefined_this.onResovledCallbacks = []_this.onRejectedCallbacks = []function resolve(value){_this.state = 'resolved'_this.value = value_this.onResolvedCallbacks.forEach(resolved => resolved(value))}function reject(reason){_this.state = 'rejected'_this.reason = reason_this.onRejectedCallbacks.forEach(rejected=> rejected(reason))}exector(resolve, reject) } Promise.prototype.then = function(onFulfilled, onRejected){if(this.state === 'resolved'){onFulfilled(this.value)}if(this.state === 'rejected'){onRejected(this.reason)}if(this.state === 'pending'){if(typeof onFulfilled === 'function'){this.onResolvedCallbacks.push(onFulfilled)}if(typeof onRejected === 'function'){this.onRejectedCallbacks.push(onRejected)}} }快排
思路: 將每次的第一個元素作為基準,將比基準小的放在left數組中,比基準大的放在right數組中.然后返回[left, pivot,right]
function qSort(arr){let pivot,left = [],right = []function loop(arr){pivot = arr[0]left = []right = []for(let i=0, len = arr.length; i < len; i++){if(arr[i] > pivot){right.push(arr[i])} else{left.push(arr[i])}}return loop(left).concat(pivot, loop(right))}return loop(arr) }冒泡排序
思路:
- 記錄待排序的數組長度 len
- 當len大于0時,會進入循環
- 會使用nextLen保存下次循環的長度.(為undefined會跳出循環)
- 每次循環都從第0號位開始,最后到len.
- 比較左右2邊的元素
- 左 > 右: 則交換左右兩邊的位置,并將nextLen置為當前的下標
- 每次到循環結束,都會將len設為nextLen
單例模式實現 發布/訂閱 模式
-
單例模式即只有一個實例
-
發布訂閱模式,即使用addDep添加依賴.使用notify
以上實現了一個簡單的觀察者模式,下面使用單例模式對其進行改造.
簡單的說就是在使用new Observer時,返回的是同一個實例.給構造函數添加一個獲取單例的方法
class Observer{constructor(){this.events = {}this.instance = null} } Observetr.getInstance = function (){if(this.instance == null){this.instance = new Observer}return this.instance }let o1 = Observetr.getInstance() let o2 = Observetr.getInstance() console.log(o1 === o2) // true總結
以上是生活随笔為你收集整理的javascript --- 手写Promise、快排、冒泡、单例模式+观察者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS swift 2048小游戏开发教
- 下一篇: gradle idea java ssm