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