前端初学者经常会问,我如何在ajax1结束之后才启动ajax2呢?我怎么做才能在所有的ajax结束之后触发某程序呢?亦或是哎真是烦,5个ajax套在一起,原来的逻辑是什么呀!

       一个稍微有点经验的前端程序员可能会直接丢给你这样一个答案——Promise。

       首先要明确一点,promise是一个规范,它并是什么新技术,在我看来它就是一种编程方式。核心就是解决地狱回掉带来的问题,优化异步流程控制。置于什么是地狱回掉自行百度哈。。。。。。

       下面开始我们今天的重点戏码😀

        既然promise是一个规范,那么我们用js去按照规范写就好了,由于js一切皆对象的原因(其实我们在使用基础数据类型的时候用的也是对象哦,它的名字叫包装类)我们就用一个Mypromise对象来代表,接下来我们用构造+原型的方式(js常用构建类的方式)创建这个类。

        

            //初始化状态值
            var PENDING = 1,
                FULFILLED = 2,
                REJECJT = 3,
                BREACK = 4;

            function MyPromise(fn) {
                if(typeof fn !== 'function') throw new TypeError("传入参数非函数")
                var mypromise = this;
                mypromise.value = null, mypromise.status = PENDING, mypromise.resolve = null, mypromise.reject = null;
                //想象成ajax中的sucess方法
                function resolve(data) {
                    mypromise.over(FULFILLED, data);
                }
                //想象成ajax中的err方法
                function reject(err) {
                    mypromise.over(REJECJT, err);
                }
//把回掉注册到ajax中的suc与err之中 fn(resolve, reject) }
MyPromise.prototype.then = function(resolve, reject) { } MyPromise.prototype.over = function(status, value) { }

        解读一下以上代码:(es6还没普及😭,const不能用)根据规范呢,我先定义了4个常量(规范里不是三个吗,你怎么是4个呀,山人自有妙计😀)。然后呢按照异步方法的通用特点,存在失败和成功的回掉,去初始化这个类,并在原型中定义了核心then方法以及ajax回掉之后都会触发的over方法(为什么要有over方法呢——减少重复)。

        接下来看看over的具体实现:

           MyPromise.prototype.over = function(status, value) {
                var mypromise = this,
                    callback = null;
                if(mypromise.status === BREACK) return;
                mypromise.status = status, mypromise.value = value;
                setTimeout(function() {
                    callback = (status === FULFILLED ? mypromise.resolve : mypromise.reject);
                    callback && callback(value)
                })
            }

         请先忽略我红色部分的代码🙂,over中会根据ajax回掉的类型(失败,成功)来触发对应的注册在该promise上的resolve与reject且只有当callback存在才能执行。置于为什么要将回掉放到settimeout中去呢,为了使后面的then方法先执行。

         重头戏then:

 MyPromise.prototype.then = function(resolve, reject) {
                var mypromise = this;
                return new MyPromise(function(onResolv, onReject) {
                    function trigerResolv(value) {
                        var nextPromise = typeof resolve === 'function' && resolve(value) || value
                        if(nextPromise instanceof MyPromise) {
                            nextPromise.then(function(value) {
                                onResolv(value);
                            }, function(value) {
                                onReject(value);
                            })
                        } else {
                            //判断在成功之后是否需要终止回掉
                            if(nextPromise === BREACK) {
                                mypromise.status = BREACK;
                                return;
                            }
                            onResolv(nextPromise);
                        }
                    }

                    function trigerReject(value) {
                        var nextPromise = typeof reject === 'function' && reject(value) || value
                        onReject(nextPromise)
                    }
                    if(mypromise.status === PENDING) {
                        mypromise.resolve = trigerResolv;
                        mypromise.reject = trigerReject;
                    }
                    if(mypromise.status === FULFILLED) {
                        trigerResolv(mypromise.value)
                    }
                    if(mypromise.status === REJECJT) {
                        trigerReject(mypromise.value)
                    }
                })
            }

         每一个then新建并返回promiseB对象(实现链式调用),对then方法中resolve进行封装,生成方法a赋值给上一个promiseA的回掉方法中。promiseA回掉方法触发之后触发a。如果返回值为promiseC对象,那么将promiseB的回掉放到promiseC的回掉之中,否则在promiseC中传入promiseA的value.

         现在来仔细看看红色部分的代码,是不是有所领悟呢?当ajax成功的时候也需要终止整个流程时就需要这第四中状态了,使用方法就是在then中的resolve中return
BREACK就ok了,当在then方法中返回BREACK的就之后,那么上文中的promiseB的回掉不会执行,也就无法触发promiseB中注册的then方法了。

         运行结果

 

 

参考:http://www.ituring.com.cn/article/66566

           http://www.cnblogs.com/huansky/p/6064402.html

posted on 2018-05-01 23:53  爬虫一只  阅读(163)  评论(0编辑  收藏  举报