通过自定义编写promise,可以更加深刻理解Promise的用法,以及学会对别人封装的代码做定制化使用。
/** * 自定义Promise函数模块,IIFE */ (function(window) { const PENDING = ‘pending‘; const RESOLVED = ‘resolved‘; const REJECTED = ‘rejected‘; /** * Promise构造函数 * executor: 执行器函数(同步执行) */ function Promise(executor) { const self = this; self.status = PENDING; //给promise对象指定status属性,初始值为pending self.data = undefined; //给promise对象指定一个用于存储结果数据的属性 self.callbacks = []; //每个元素的数据结构: {onResolved(){}, onReject(){}} function resolve(value) { //如果当前状态不是pending,直接结束 if(self.status !== PENDING) { return; } //状态为resolved self.status = RESOLVED; //保存value数据 self.data = value; //如果有待执行的callback函数,立即异步执行回调函数onResolved if(self.callbacks.length>0) { setTimeout(() => { self.callbacks.forEach(callbacksObj => { callbacksObj.onResolved(value); }) }) } } function reject(reason) { //如果当前状态不是pending,直接结束 if(self.status !== PENDING) { return; } //状态为rejected self.status = REJECTED; //保存value数据 self.data = reason; //如果有待执行的callback函数,立即异步执行回调函数onResolved if(self.callbacks.length>0) { setTimeout(() => { self.callbacks.forEach(callbacksObj => { callbacksObj.onRejected(reason); }) }) } } try { executor(resolve, reject); } catch (error) { // 如果执行器抛出异常,primose对象变成rejected状态 reject(error); } } /** * Promise原型对象的then() * 指定成功和失败的回调函数 * 返回一个新的promise对象 */ Promise.prototype.then = function(onResolved, onRejected) { //向后传递成功的value onResolved = typeof onResolved === ‘function‘ ? onResolved : value => value //指定默认的失败的回调(实现错误/异常穿透的关键点),向后传递失败的reason onRejected = typeof onRejected === ‘function‘ ? onRejected : reason => {throw reason} const self = this; //返回一个新的promise对象 return new Promise((resolve, reject) => { //调用指定的回调函数处理,根据执行的结果改变return的promise状态 function handle(callback) { /** * 1.如果抛出异常,return的promise就会失败,reason就是error * 2.如果回调函数返回不是promise,return的promise就会成功,value就是返回的值 * 3.如果回调函数返回是promise,return的promise就是这个promise结果 */ try { const result = callback(self.data); if(result instanceof Promise) { // result.then( // value => resolve(value), //当result成功时,让return的promise也成功 // reason => reject(reason) //当result失败时,让return的promise也失败 // ) result.then(resolve, reject); } else { resolve(result); } } catch(error) { reject(error); } } if(self.status === PENDING) { //假设当前还是pending状态,将回调函数保存起来 self.callbacks.push({ onResolved() { handle(onResolved) }, onRejected() { handle(onRejected) } }) } else if(self.status === RESOLVED) { //如果当前是resolved状态,异步执行onResolved函数并改变return的promise状态 setTimeout(() => { handle(onResolved); }) } else { //如果当前是rejected状态,异步执行onRejected函数并改变return的promise状态 setTimeout(() => { handle(onRejected); }) } }); } /** * Promise原型对象的catch() * 指定失败的回调函数 * 返回一个新的promise函数 */ Promise.prototype.catch = function(onRejected) { return this.then(undefined, onRejected); } // 函数对象方法,也即工具方法 /** * Promise函数对象的resolve方法 * 返回一个指定成功结果value的promise */ Promise.resolve = function(value) { //返回一个成功/失败的promise return new Promise((resolve, reject) => { //value是promise if(value instanceof Promise) { value.then(resolve, reject); } else { //value不是promise resolve(value); } }) } /** * Promise函数对象的reject方法 * 返回一个指定失败结果reason的promise */ Promise.reject = function(reason) { //返回一个失败的promise return new Promise((resolve, reject) => { reject(reason); }) } /** * Promise函数对象的all方法 */ Promise.all = function(promises) { // 保存所有成功的value数组 const values = new Array(promises.length); // 用来保存成功的promise的数量 let resolvedCount = 0; return new Promise((resolve, reject) => { //遍历获取每一个primise的结果 promises.forEach((p, index) => { Promise.resolve(p).then( value => { resolvedCount++; //成功的数量加1 values[index] = value; //p成功了,将成功的value按照顺序保存到values中 //如果全部成功了,将return的promise改为成功 if(resolvedCount === promises.length) { resolve(values); } }, reason => { reject(reason); } ) }) }) } /** * Promise函数对象的race方法 * 返回新的promise,其结果由第一个完成的promise决定 */ Promise.race = function(promises) { //返回一个promise return new Promise((resolve, reject) => { //遍历获取每一个primise的结果 promises.forEach((p, index) => { Promise.resolve(p).then( //Promise.resolve(p) 包装了下p为promise,兼容数组中非promise的值 value => { //一旦有成功,将return变成成功 resolve(value); }, reason => { //一旦有失败,将return变成失败 reject(reason); } ) }) }) } /** * 返回一个promise对象,它在指定的时间后才确定结果 */ Promise.resolveDelay = function(value, time) { //返回一个成功/失败的promise return new Promise((resolve, reject) => { setTimeout(() => { //value是promise if(value instanceof Promise) { value.then(resolve, reject); } else { //value不是promise resolve(value); } }, time) }) } /** * 返回一个promise对象,它在指定的时间后才失败 */ Promise.rejectDelay = function(reason, time) { //返回一个失败的promise return new Promise((resolve, reject) => { setTimeout(() => { reject(reason); }, time) }) } // 向外暴露Promise函数 window.Promise = Promise })(window)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="./promise.js"></script> <script type="text/javascript"> // console.log(new Promise().status) // const p = new Promise((resolve, reject) => { // setTimeout(() =>{ // // resolve(1); // reject(2); // console.log(‘-----‘) // }, 100) // }) // p.then( // value => { // console.log(‘onResolve1()‘, value); // }, // reason => { // console.log(‘onRejected1()‘, reason); // } // ) // p.then( // value => { // console.log(‘onResolve2()‘, value); // }, // reason => { // console.log(‘onRejected2()‘, reason); // } // ) const p = new Promise((resolve, reject) => { setTimeout(() =>{ resolve(1); // reject(2); console.log(‘-----‘) }, 100) }).then( value => { console.log(‘onResolve1()‘, value); return new Promise((resolve, reject) => reject(5)) }, reason => { console.log(‘onRejected1()‘, reason); return 4; } ).then( value => { console.log(‘onResolve2()‘, value); }, reason => { console.log(‘onRejected2()‘, reason); throw 6; } ).catch( reason => { console.log(‘onRejected catch()‘, reason); return new Promise(()=>{}) } ).then( value => { console.log(‘onResolve3()‘, value); }, reason => { console.log(‘onRejected3()‘, reason); throw 6; } ) </script> </head> <body> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="./promise.js"></script> <script type="text/javascript"> const p1 = Promise.resolve(2); const p2 = Promise.resolve(Promise.resolve(3)); const p3 = Promise.resolve(Promise.reject(4)); p1.then(value => {console.log(‘p1‘, value)}) p2.then(value => {console.log(‘p2‘, value)}) p3.catch(reason => {console.log(‘p3‘, reason)}) </script> </head> <body> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="./promise.js"></script> <script type="text/javascript"> const p1 = Promise.resolve(2); const p2 = Promise.resolve(Promise.resolve(3)); const p3 = Promise.resolve(Promise.reject(4)); const p4 = new Promise((resolve) => { setTimeout(() => { resolve(5); }, 1000) }) const pAll = Promise.all([p4, p1, p2]); pAll.then( values => { console.log(‘all onResolved()‘, values); }, reasons => { console.log(‘all onRejected()‘, reasons); } ) // const pRace = Promise.race([p1, p2, p3]); // pRace.then( // value => { // console.log(‘race onResolved()‘, value); // }, // reason => { // console.log(‘race onRejected()‘, reason); // } // ) </script> </head> <body> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="./promise.js"></script> <script type="text/javascript"> const p1 = Promise.resolve(2); const p2 = Promise.resolve(Promise.resolve(3)); const p3 = Promise.resolve(Promise.reject(4)); const p4 = new Promise((resolve) => { setTimeout(() => { resolve(5); }, 1000) }) const p5 = Promise.reject(6) const pRace = Promise.race([p4, p5, p3]); pRace.then( value => { console.log(‘race onResolved()‘, value); }, reason => { console.log(‘race onRejected()‘, reason); } ) const p6 = Promise.resolveDelay(66, 3000); const p7 = Promise.rejectDelay(77, 2000); p6.then( value => { console.log(value); } ) p7.catch( reason => { console.log(reason); } ) </script> </head> <body> </body> </html>
当然,还能改造为class对象
/** * 自定义Promise函数模块,IIFE */ (function(window) { const PENDING = ‘pending‘; const RESOLVED = ‘resolved‘; const REJECTED = ‘rejected‘; class Promise() { /** * Promise构造函数 * executor: 执行器函数(同步执行) */ constructor(executor) { const self = this; self.status = PENDING; //给promise对象指定status属性,初始值为pending self.data = undefined; //给promise对象指定一个用于存储结果数据的属性 self.callbacks = []; //每个元素的数据结构: {onResolved(){}, onReject(){}} function resolve(value) { //如果当前状态不是pending,直接结束 if(self.status !== PENDING) { return; } //状态为resolved self.status = RESOLVED; //保存value数据 self.data = value; //如果有待执行的callback函数,立即异步执行回调函数onResolved if(self.callbacks.length>0) { setTimeout(() => { self.callbacks.forEach(callbacksObj => { callbacksObj.onResolved(value); }) }) } } function reject(reason) { //如果当前状态不是pending,直接结束 if(self.status !== PENDING) { return; } //状态为rejected self.status = REJECTED; //保存value数据 self.data = reason; //如果有待执行的callback函数,立即异步执行回调函数onResolved if(self.callbacks.length>0) { setTimeout(() => { self.callbacks.forEach(callbacksObj => { callbacksObj.onRejected(reason); }) }) } } try { executor(resolve, reject); } catch (error) { // 如果执行器抛出异常,primose对象变成rejected状态 reject(error); } } /** * Promise原型对象的then() * 指定成功和失败的回调函数 * 返回一个新的promise对象 */ then(onResolved, onRejected) { //向后传递成功的value onResolved = typeof onResolved === ‘function‘ ? onResolved : value => value //指定默认的失败的回调(实现错误/异常穿透的关键点),向后传递失败的reason onRejected = typeof onRejected === ‘function‘ ? onRejected : reason => {throw reason} const self = this; //返回一个新的promise对象 return new Promise((resolve, reject) => { //调用指定的回调函数处理,根据执行的结果改变return的promise状态 function handle(callback) { /** * 1.如果抛出异常,return的promise就会失败,reason就是error * 2.如果回调函数返回不是promise,return的promise就会成功,value就是返回的值 * 3.如果回调函数返回是promise,return的promise就是这个promise结果 */ try { const result = callback(self.data); if(result instanceof Promise) { // result.then( // value => resolve(value), //当result成功时,让return的promise也成功 // reason => reject(reason) //当result失败时,让return的promise也失败 // ) result.then(resolve, reject); } else { resolve(result); } } catch(error) { reject(error); } } if(self.status === PENDING) { //假设当前还是pending状态,将回调函数保存起来 self.callbacks.push({ onResolved() { handle(onResolved) }, onRejected() { handle(onRejected) } }) } else if(self.status === RESOLVED) { //如果当前是resolved状态,异步执行onResolved函数并改变return的promise状态 setTimeout(() => { handle(onResolved); }) } else { //如果当前是rejected状态,异步执行onRejected函数并改变return的promise状态 setTimeout(() => { handle(onRejected); }) } }); } /** * Promise原型对象的catch() * 指定失败的回调函数 * 返回一个新的promise函数 */ catch(onRejected) { return this.then(undefined, onRejected); } // 函数对象方法,也即工具方法 /** * Promise函数对象的resolve方法 * 返回一个指定成功结果value的promise */ static resolve = function(value) { //返回一个成功/失败的promise return new Promise((resolve, reject) => { //value是promise if(value instanceof Promise) { value.then(resolve, reject); } else { //value不是promise resolve(value); } }) } /** * Promise函数对象的reject方法 * 返回一个指定失败结果reason的promise */ static reject = function(reason) { //返回一个失败的promise return new Promise((resolve, reject) => { reject(reason); }) } /** * Promise函数对象的all方法 */ static all = function(promises) { // 保存所有成功的value数组 const values = new Array(promises.length); // 用来保存成功的promise的数量 let resolvedCount = 0; return new Promise((resolve, reject) => { //遍历获取每一个primise的结果 promises.forEach((p, index) => { Promise.resolve(p).then( value => { resolvedCount++; //成功的数量加1 values[index] = value; //p成功了,将成功的value按照顺序保存到values中 //如果全部成功了,将return的promise改为成功 if(resolvedCount === promises.length) { resolve(values); } }, reason => { reject(reason); } ) }) }) } /** * Promise函数对象的race方法 * 返回新的promise,其结果由第一个完成的promise决定 */ static race = function(promises) { //返回一个promise return new Promise((resolve, reject) => { //遍历获取每一个primise的结果 promises.forEach((p, index) => { Promise.resolve(p).then( //Promise.resolve(p) 包装了下p为promise,兼容数组中非promise的值 value => { //一旦有成功,将return变成成功 resolve(value); }, reason => { //一旦有失败,将return变成失败 reject(reason); } ) }) }) } /** * 返回一个promise对象,它在指定的时间后才确定结果 */ static resolveDelay = function(value, time) { //返回一个成功/失败的promise return new Promise((resolve, reject) => { setTimeout(() => { //value是promise if(value instanceof Promise) { value.then(resolve, reject); } else { //value不是promise resolve(value); } }, time) }) } /** * 返回一个promise对象,它在指定的时间后才失败 */ static rejectDelay = function(reason, time) { //返回一个失败的promise return new Promise((resolve, reject) => { setTimeout(() => { reject(reason); }, time) }) } } // 向外暴露Promise函数 window.Promise = Promise })(window)
注意点:
1、函数对象和实例对象的区别
2、同步调用和异步调用
3、Promise的几个API
原文:https://www.cnblogs.com/jerryleeplus/p/12122231.html