当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 手动实现Promise

手动实现Promise

2019年04月18日  | 移动技术网IT编程  | 我要评论
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);

  执行结果:

  

   实现过程简单粗暴,如有问题,烦请指出,谢谢!

 

 

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网