摘要:最近研究了一下的實現,這篇文章使用了十幾行代碼實現了一個簡單的以便幫助讀者對有更深的了解。另外一個有三種狀態。所以我們有以下的代碼然后我們實現函數每次函數的執行會返回一個新的。因為這行代碼是異步執行的,而當中的時,這行代碼不應該執行。
最近研究了一下promise的實現,這篇文章使用了十幾行代碼實現了一個簡單的promise;以便幫助讀者對promise"有更深的了解。本篇文章實現的promise,遵循規范是 Promises/A+。
閱讀本篇文章時,已經假定你會promise的基本使用和一些簡單的es6語法;如果你還沒掌握promise的基本使用,請學習完畢后再來。推薦可以看《promise迷你書》、《你不知道的js》及阮一峰老師的《ECMAScript 6 入門》。
promise的核心實現首先,我們看一下一個promise的基本用法:
var p = new MyPromise((resolve) => { setTimeout(() => { resolve(20) }, 300) }) p.then( (msg) => console.log(msg) );
MyPromise是一個構造函數,這個構造函數會被傳遞一個函數;函數中有兩個參數,是兩個函數resolve,reject。另外一個promise有三種狀態PENDING、RESOLVED、REJECTED。所以我們有以下的代碼:
const PENDING = 0; const RESOLVED = 1; const REJECTED = 2; function MyPromise(func){ let state = PENDING; let value = null; function resolve(newValue){ value = newValue; state = RESOLVED; } function reject(err){ value = err; state = REJECTED; } func(resolve, reject); }
然后我們實現then函數,每次then函數的執行會返回一個新的promise。
this.then = function(onFullFill, onReject){ return new MyPromise((resolve, reject) => { }) }
傳遞給then函數onFullFill函數返回值,會傳遞給第二個then中onFullFill中。即要能這樣使用p.then( (msg) => msg ).then( data => console.log(data) );
這行代碼實際是什么呢?讓我們變換一下上面的代碼:
p .then( function fn1(msg){ return msg; }) .then( function fn2(data){ console.log(data); }) //以上代碼的實質 fn2(fn1(msg))
我們要在then函數里面如何執行resolve函數呢?首先resolve函數是必須執行的,因為它要改變p.then()生成的promise的狀態;其次,resolve這個函數還要能接受到onFullFill執行的值;以便傳遞給下一個回調函數。你可能想到了這種方案:
const PENDING = 0; const RESOLVED = 1; const REJECTED = 2; function MyPromise(func){ let state = PENDING; let value = null; function resolve(newValue){ value = newValue; state = RESOLVED; } function reject(err){ value = err; state = REJECTED; } this.then = function(onFullFill, onReject){ return new MyPromise((resolve, reject) => { resolve(onFullFill(value)); }) } func(resolve, reject); } var p = new MyPromise((resolve) => { setTimeout(() => { resolve(20) }, 300) }) p.then( (msg) => msg ).then( data => console.log(data) );
但是當你把以上代碼拼湊在一起,執行;打印出來的是null。why?
因為setTimeout(fn, 300)這行代碼是異步執行的,而當promise中的state!==RESOLVED時,這行代碼resolve(onFullFill(value));不應該執行。所以我們有了以下的優化:
function MyPromise(func){ let state = PENDING; let value = null; let handlers = []; function resolve(newValue){ value = newValue; state = RESOLVED; handlers.forEach( handler => handle(handler)); } function reject(err){ value = err; state = REJECTED; } function handle(handler){ if(state === PENDING){ handlers.push(handler); return; } handler.resolve(handler.onFullFill(value)); } this.then = function(onFullFill, onReject){ return new MyPromise((resolve, reject) => { handle({ resolve: resolve, onFullFill: onFullFill }) }) } func(resolve, reject); }
這樣在then函數里和resolve函數里我們都會執行handle函數,但只有在resolve函數執行后才會執行handler.resolve(handler.onFullFill(value))。
現在還有一個問題,如果Promise中封裝的不是異步操作,而是同步操作;那么resolve函數就會比then函數更先執行。
var p = new MyPromise((resolve, reject) => { resolve("同步操作") }) p.then(console.log)
所以我們執行resolve中的回調的時候,應該異步執行:
function resolve(newValue){ value = newValue; state = RESOLVED; setTimeout( () => { handlers.forEach( handler => handle(handler)); }, 0) }
同時,由于then函數中可以接收一個promise;我們需要對這種情況進行處理:
function resolve = (newValue) => { if(newValue && (typeof newValue === "object" || typeonewValue === "function") { let then = newValue.then if(typeof then === "function"){ return then.call(newValue, resolve) } state = FULFILLED; value = newValue; setTimeout(() => { handlers.forEach(handler => { handle(handler) }) }, 0) }
至此,我們已經完成了一個基本promise的實現。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83498.html
摘要:最近研究了一下的實現,這篇文章使用了十幾行代碼實現了一個簡單的以便幫助讀者對有更深的了解。另外一個有三種狀態。所以我們有以下的代碼然后我們實現函數每次函數的執行會返回一個新的。因為這行代碼是異步執行的,而當中的時,這行代碼不應該執行。 最近研究了一下promise的實現,這篇文章使用了十幾行代碼實現了一個簡單的promise;以便幫助讀者對promise有更深的了解。本篇文章實現的pr...
摘要:開發一個自己的腳手架了解了一些腳手架的工作方式與的基本概念,咱們就可以來創建一個屬于自己的腳手架。引言 下面是一個使用腳手架來初始化項目的典型例子。 ? showImg(https://user-gold-cdn.xitu.io/2019/5/16/16ac081750971790); ? ? 隨著前端工程化的理念不斷深入,越來越多的人選擇使用腳手架來從零到一...
摘要:期函數式編程中代碼組合如何理解定義顧名思義,在函數式編程中,就是將幾個有特點的函數拼湊在一起,讓它們結合,產生一個嶄新的函數代碼理解一個將小寫轉大寫的函數一個在字符后加的函數將兩個函數組合起來這里假設我們實現了每日一題每日一題顯示結果里上面 20190315期 函數式編程中代碼組合(compose)如何理解? 定義: 顧名思義,在函數式編程中,Compose就是將幾個有特點的函數拼湊在...
摘要:為的內置一個方法,用法和原生的事件機制一毛一樣。 前言 上兩篇Mvvm教程的熱度超出我的預期,很多碼友留言表揚同時希望我繼續出下一篇教程,當時我也半開玩笑說只要點贊超10就兌現承諾,沒想到還真破了10,所以就有了今天的文章。 準備工作 熟讀 【教學向】150行代碼教你實現一個低配版的MVVM庫(1)- 原理篇【教學向】150行代碼教你實現一個低配版的MVVM庫(2)- 代碼篇 本篇是在...
閱讀 2060·2021-11-23 09:51
閱讀 2202·2021-09-29 09:34
閱讀 3694·2021-09-22 15:50
閱讀 3556·2021-09-22 15:23
閱讀 2556·2019-08-30 15:55
閱讀 699·2019-08-30 15:53
閱讀 3065·2019-08-29 17:09
閱讀 2623·2019-08-29 13:57