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