手动实现Promise
程序员文章站
2022-11-27 14:42:32
Promise对大家来说并不是很陌生,它是一个异步编程的解决方案,主要解决了前端回调地域问题。用阮老师的话说,它“就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果”。 Promise有三种状态:pending(初始状态)、fulfilled(成功)、reject(失败),初 ......
promise对大家来说并不是很陌生,它是一个异步编程的解决方案,主要解决了前端回调地域问题。用阮老师的话说,它“就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果”。
promise有三种状态:pending(初始状态)、fulfilled(成功)、reject(失败),初始状态pending只能变成fulfilled或者reject,这一过程是不可逆的,当状态发生改变时,会触发对应的回调方法。除此之外,也支持链式调用,then/catch会返回一个promise,以供链式调用,盗用mdn上的一张图,promise的执行流程如下图所示:
具体实现简单分为以下四步:
1、定义一个执行器fn,自带两个参数的函数,resolve/reject,在实例化promise时,调用执行器fn,传入参数reslove/reject,初始化回调事件队列tasklist
2、在执行then方法时,判断是不是初始状态pending,如果是,则将then中fullfilled/reject的回调推进执行队列tasklist中,then方法返回一个promise实例
3、实现链式回调中,用id来标识不同的promise实例
4、当触发了执行器中参数函数时,根据id来判断当前执行的回调方法
实现代码:
1 //公共变量,用于标识mypromise实例 2 index = 0; 3 //promise接收一个回调函数fn,有两个参数,reslove,reject 4 function mypromise(fn) { 5 var _this = this; 6 //promise的三种状态 7 this.resolve = "fullfilled"; 8 this.pending = "pending"; 9 this.reject = "reject"; 10 this.id = index++; 11 //初始默认状态为penddding 12 this.state = this.pending; 13 //执行任务列表 14 this.tasklist = []; 15 //最终执行的回调 16 this.finallycallback = null; 17 //bind改变reslove/reject函数体内this的指向,确保指向mypromise 18 fn.call(this, this.resolve.bind(this), this.reject.bind(this)); 19 } 20 21 mypromise.prototype.resolve = function(value) { 22 this.state = this.resolve; 23 //2、状态变更时,执行完成的方法 24 this.tasklist[this.id] && this.handler(this.tasklist[this.id], value); 25 }; 26 27 mypromise.prototype.reject = function(value) { 28 this.state = this.reject; 29 //2、状态变更时,执行完成的方法 30 this.tasklist[this.id] && this.handler(this.tasklist[this.id], value); 31 }; 32 //执行任务回调 33 mypromise.prototype.handler = function(task, value) { 34 var result = null; 35 if (this.state === this.resolve) { 36 result = task.onfullfilled(value); 37 } else if (this.state === this.reject) { 38 result = task.onreject(value); 39 } 40 var nextid = this.id + 1; 41 //需要判断返回值是不是mypromise实例,如果是,将之前的任务队列赋值给新的mypromise实例 42 if (result instanceof mypromise) { 43 result.id = nextid; 44 result.tasklist = this.tasklist; 45 result.finallycallback = this.finallycallback; 46 } else { 47 //没有返回mypromise实例 48 //如果有finally回调,则执行最终的回调 49 this.finallycallback && this.finallycallback(); 50 } 51 }; 52 //onfullfilled:成功的回调,onreject:失败的回调 53 mypromise.prototype.then = function(onfullfilled, onreject) { 54 var _this = this, 55 obj = { 56 onfullfilled: onfullfilled, 57 onreject: onreject 58 }; 59 //1、初始化时,将后续可能要执行的任务推送到执行任务队列中 60 if (this.state === this.pending) { 61 this.tasklist.push(obj); 62 } 63 //返回一个promise,支持链式调用 64 return this; 65 }; 66 67 //最终执行的方法,不管mypromise的状态如何 68 mypromise.prototype.finally = function(callback) { 69 this.finallycallback = callback; 70 };
测试代码:
var cc = new mypromise(function(reslove, reject) { settimeout(function() { reslove(2); }, 500); }); var dd = new mypromise(function(reslove, reject) { settimeout(function() { reject(3); }, 500); }); cc.then(function(num) { console.log(num); return dd; }) .then( function(cc) { console.log(cc); }, function(e) { console.log(5); } ) .finally(function() { console.log("game over"); }); console.log(1);
执行结果:
实现过程简单粗暴,如有问题,烦请指出,谢谢!
上一篇: 小程序canvas中文字设置居中锚点
下一篇: Python中的cheetah模板