promise是什么?简单分析promise原理
生活随笔
收集整理的這篇文章主要介紹了
promise是什么?简单分析promise原理
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
預(yù)備知識(shí)
- 回調(diào)函數(shù)
- 高級(jí)函數(shù)
- 發(fā)布-訂閱模式
- promise A+ 規(guī)范
promise是什么,能干什么
Promise是異步編程的一種解決方案,它可以解決異步回調(diào)地獄的問題,防止層層嵌套對(duì)程序代碼帶來的難維護(hù)性。既然帶來了方便,我們就有必要學(xué)習(xí)它的原理以及底層實(shí)現(xiàn),所以筆者就按照PromiseA+規(guī)范寫了一個(gè)簡單的Promise,并實(shí)現(xiàn)了Promise.all(),Promise.race()等API
- 解決回調(diào)地獄
- 解決多個(gè)回調(diào)函數(shù)同步結(jié)果
promise的幾個(gè)方法
- promise.all()
- promise.race()
- promise.resolve()
- promise.reject()
promise的三種狀態(tài)
- 等待態(tài) pending
- 成功態(tài) resolved
- 失敗態(tài) rejected
promise的特點(diǎn)
- 1.executor 默認(rèn)時(shí)new的時(shí)候就自動(dòng)執(zhí)行
- 2.每個(gè)promise的實(shí)例 都有then方法
- 3.then方法中有兩個(gè)參數(shù) 分別是成功的回調(diào)和失敗的回調(diào)
- 4.then方法是異步的(微任務(wù)) // 微任務(wù)先于宏任務(wù)執(zhí)行
- 5.同一個(gè)promise的實(shí)例可以then多次,成功時(shí)回調(diào)用所有的成功方法,失敗時(shí)會(huì)調(diào)用所有的失敗方法
- 6.new Promise中可以支持異步行為
- 7.如果發(fā)現(xiàn)錯(cuò)誤就會(huì)走入失敗態(tài)
下一次的輸入需要上一次的輸出 (有依賴關(guān)系)
- 1.如果一個(gè)promise執(zhí)行完后 返回的還是一個(gè)promise,會(huì)把這個(gè)promise 的執(zhí)行結(jié)果,傳遞給下一次then中
- 2.如果then中返回的不是promise 是一個(gè)普通值,會(huì)將這個(gè)普通值作為下次then的成功的結(jié)果
- 3.如果當(dāng)前then中失敗了 會(huì)走下一個(gè)then的失敗
- 4.如果返回的是undefined 不管當(dāng)前是成功還是失敗 都會(huì)走下一次的成功
- 5.catch是錯(cuò)誤沒有處理的情況下才會(huì)走
- 6.then中可以不寫東西,相當(dāng)于白寫 (值的穿透)
promise A+ 規(guī)范
- 原文
- 翻譯
- 校驗(yàn)插件 npm install promises-aplus-tests -g 用于檢查自己寫的promise是否符合promise規(guī)范
簡單實(shí)現(xiàn) 待完善
function Promise(executor){let self = this;self.value = undefined; // 成功時(shí)的參數(shù)self.reason = undefined; // 失敗時(shí)的參數(shù)self.status = 'pending'; // 狀態(tài) self.onResolvedCallbacks = [];// 存放then中成功的回調(diào) self.onRejectedCallbacks = []; // 存放then中失敗的回調(diào) function resolve(value){ // if(self.status === 'pending'){self.value = value;self.status = 'resolved';self.onResolvedCallbacks.forEach(fn=>fn());}}function reject(reason){if(self.status === 'pending'){self.reason = reason;self.status = 'rejected';self.onRejectedCallbacks.forEach(fn=>fn());}}// 如果函數(shù)執(zhí)行時(shí)發(fā)生異常 就走到失敗中try{executor(resolve,reject);}catch(e){reject(e);} } Promise.prototype.then = function(onFulfilled,onRejected){let self = this;if(self.status === 'resolved'){onFulfilled(self.value);}if(self.status === 'rejected'){onRejected(self.reason);}if(self.status === 'pending'){// 保存回調(diào)函數(shù)self.onResolvedCallbacks.push(()=>{onFulfilled(self.value);});self.onRejectedCallbacks.push(()=>{onRejected(self.reason)});} } module.exports = Promise; 復(fù)制代碼基本實(shí)現(xiàn)
function Promise(executor) {let self = this;self.value = undefined; // 成功的值self.reason = undefined; // 失敗的原因self.status = 'pending'; // 值是pending狀態(tài)self.onResolvedCallbacks = []; // 可能new Promise的時(shí)候會(huì)有異步操作,保存成功和失敗的回調(diào) self.onRejectedCallbacks = [];function resolve(value) { // 把狀態(tài)改成成功態(tài)if (self.status === 'pending') { // 只有等待態(tài) 可以改變狀態(tài)self.value = value;self.status = 'resolved';self.onResolvedCallbacks.forEach(fn => fn());}}function reject(reason) { // 把狀態(tài)改成失敗態(tài)if (self.status === 'pending') {self.reason = reason;self.status = 'rejected';self.onRejectedCallbacks.forEach(fn => fn());}}try {// 默認(rèn)new Promise時(shí) 應(yīng)該執(zhí)行對(duì)應(yīng)的執(zhí)行器(同步執(zhí)行)executor(resolve, reject);} catch (e) { // 如果執(zhí)行exectuor時(shí) 發(fā)生錯(cuò)誤 就會(huì)讓當(dāng)前的promise變成失敗態(tài)reject(e);} } /*** * @param {*} promise2 then的返回值 (返回的新的promise)* @param {*} x then中成功或者失敗函數(shù)的返回值* @param {*} resolve promise2的resolve* @param {*} reject promise2的reject*/ // 所有的promise都遵循這個(gè)規(guī)范 (所有的promise可以通用)function resolvePromise(promise2,x,resolve,reject){// promise2和函數(shù)執(zhí)行后返回的結(jié)果是同一個(gè)對(duì)象if(promise2 === x){ return reject(new TypeError('Chaining cycle'));}let called;// x可能是一個(gè)promise 或者是一個(gè)普通值if(x!==null && (typeof x=== 'object' || typeof x === 'function')){try{let then = x.then; // 取對(duì)象上的屬性 怎么能報(bào)異常呢?(這個(gè)promise不一定是自己寫的 可能是別人寫的 有的人會(huì)亂寫)// x可能還是一個(gè)promise 那么就讓這個(gè)promise執(zhí)行即可// {then:{}}// 這里的邏輯不單單是自己的 還有別人的 別人的promise 可能既會(huì)調(diào)用成功 也會(huì)調(diào)用失敗if(typeof then === 'function'){then.call(x,y=>{ // 返回promise后的成功結(jié)果// 遞歸直到解析成普通值為止if(called) return; // 防止多次調(diào)用called = true;// 遞歸 可能成功后的結(jié)果是一個(gè)promise 那就要循環(huán)的去解析resolvePromise(promise2,y,resolve,reject);},err=>{ // promise的失敗結(jié)果if(called) return;called = true;reject(err);});}else{resolve(x);}}catch(e){if(called) return;called = true;reject(e);}}else{ // 如果x是一個(gè)常量resolve(x);} } // then調(diào)用的時(shí)候 都是異步調(diào)用 (原生的then的成功或者失敗 是一個(gè)微任務(wù)) Promise.prototype.then = function (onFulfilled, onRejected) {// 成功和失敗的回調(diào) 是可選參數(shù)// onFulfilled成功的回調(diào) onRejected失敗的回調(diào)let self = this;let promise2;// 需要沒次調(diào)用then時(shí)都返回一個(gè)新的promisepromise2 = new Promise((resolve, reject) => {if (self.status === 'resolved') {setTimeout(()=>{try {// 當(dāng)執(zhí)行成功回調(diào)的時(shí)候 可能會(huì)出現(xiàn)異常,那就用這個(gè)異常作為promise2的錯(cuò)誤的結(jié)果let x = onFulfilled(self.value);//執(zhí)行完當(dāng)前成功回調(diào)后返回結(jié)果可能是promiseresolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'rejected') {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'pending') {self.onResolvedCallbacks.push(() => {setTimeout(()=>{try {let x = onFulfilled(self.value);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});self.onRejectedCallbacks.push(() => {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});}});return promise2 } // 為什么加setTimeout (規(guī)范要求的)Promise.defer = Promise.deferred = function(){let dfd = {};dfd.promise = new Promise((resolve,reject)=>{dfd.resolve = resolve;dfd.reject = reject;})return dfd; } module.exports = Promise; 復(fù)制代碼最終版本
function Promise(executor) {let self = this;self.value = undefined; self.reason = undefined; self.status = 'pending';self.onResolvedCallbacks = [];self.onRejectedCallbacks = [];function resolve(value) { if (self.status === 'pending') {self.value = value;self.status = 'resolved';self.onResolvedCallbacks.forEach(fn => fn());}}function reject(reason) { if (self.status === 'pending') {self.reason = reason;self.status = 'rejected';self.onRejectedCallbacks.forEach(fn => fn());}}try {executor(resolve, reject);} catch (e) { reject(e);} } function resolvePromise(promise2,x,resolve,reject){if(promise2 === x){return reject(new TypeError('Chaining cycle'));}let called;if(x!==null && (typeof x=== 'object' || typeof x === 'function')){try{let then = x.then; if(typeof then === 'function'){then.call(x,y=>{ if(called) return; called = true;resolvePromise(promise2,y,resolve,reject);},err=>{ if(called) return;called = true;reject(err);});}else{resolve(x);}}catch(e){if(called) return;called = true;reject(e);}}else{ // 如果x是一個(gè)常量resolve(x);} } Promise.prototype.then = function (onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === 'function'?onFulfilled:val=>val;onRejected = typeof onRejected === 'function'?onRejected: err=>{throw err}let self = this;let promise2;promise2 = new Promise((resolve, reject) => {if (self.status === 'resolved') {setTimeout(()=>{try {let x = onFulfilled(self.value);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'rejected') {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)}if (self.status === 'pending') {self.onResolvedCallbacks.push(() => {setTimeout(()=>{try {let x = onFulfilled(self.value);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});self.onRejectedCallbacks.push(() => {setTimeout(()=>{try {let x = onRejected(self.reason);resolvePromise(promise2,x,resolve,reject);} catch (e) {reject(e);}},0)});}});return promise2 } // 語法糖 (甜) 目的是解決promise嵌套問題的 Q.derfer() Promise.defer = Promise.deferred = function(){let dfd = {};dfd.promise = new Promise((resolve,reject)=>{dfd.resolve = resolve;dfd.reject = reject;})return dfd; } // 類上的方法 Promise.reject = function(reason){return new Promise((resolve,reject)=>{reject(reason);}) } Promise.resolve = function(value){return new Promise((resolve,reject)=>{resolve(value);}) } Promise.prototype.catch = function(onRejected){// 默認(rèn)不寫成功return this.then(null,onRejected); }; // all方法 Promise.all = function(promises){return new Promise((resolve,reject)=>{let arr = [];let i = 0;function processData(index,data){arr[index] = data;if(++i == promises.length){resolve(arr);}}for(let i = 0;i<promises.length;i++){promises[i].then(data=>{ // data是成功的結(jié)果processData(i,data);},reject);}}) } // 以請(qǐng)求最快的為準(zhǔn) Promise.race = function(promises){return new Promise((resolve,reject)=>{for(let i = 0;i<promises.length;i++){promises[i].then(resolve,reject);}}) } module.exports = Promise; 復(fù)制代碼總結(jié)
以上是生活随笔為你收集整理的promise是什么?简单分析promise原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Git区分文件名大小写
- 下一篇: 局部内部类访问它所在方法中的局部变量必须