deferred延迟对象实现思路

1: 场景铺垫 为什么需要延迟对象,它能解决什么问题,与callbacks不同点是什么

  a: 如下图所示,callbacks解决的是对函数的统一管理,,可以无限制的add添加操作,但是最终通过fire一次性全部触发

  b: 分析这样场景,如果希望对函数进行分类管理,比如一部分函数是成功的,一部分是函数是失败的,当触发时,希望通过特定的触发方式,触发不同函数集

  总结:deferred的出现就是为了解决函数的归类触发问题

  c: 关于引用知识 当创建三个cb对象,for循环每次把不同的对象赋值给变量list,然后list.firewith赋值给resolve,add赋值给done,当循环结束,list只是充当了一个中间角色,指向不同对象

    

  

 

 

 

 

2: 设计思路,首先要从需求点入手,对于web项目来说,最大的异步问题就是接口请求,而接口的请求有两个最重要的状态,成功和失败,附带一个进行中

  a: 需要一个dfd.resolve()方法 统一触发注册成功的函数,注册函数通过add,如果公用一个add,不知道向哪个list中添加,当然可以在add中带有参数指明,但是无意会给使用者造成负担,使用者更在意的是使用层面,只需要把回调函数传入就可以,所以在add调用之前,指明一个前缀函数done,可以区分到底是触发哪个

  b: 需要一个dfd.reject() 方法  统一触发注册的失败的函数,注册函数通过add,分析思路同上

3: 需求实现

  a;从需求来看,如果触发了resolve函数后,代表状态已经成功,此时触发reject应该是无效的,但是成功后还想做其它事情,那么就需要有memeory记忆功能,当调用done应该主动触发回调函数

  

 

   b:第一次触发resolve时,会触发d1函数,然后触发reject方法,此时状态已经变化就不能再次变化,所以resolve调用后,就应该把其它的cb禁用掉,使得cb2丧失一切能力,cb3锁住

 

  c: always作用,总会触发,针对的是结果,不论最终调用resolve,reject,都能实现通过always注册的函数

 

4: 代码实现层面

  a: 首先通过extend方法,把deferred扩展到ljquery上,add可以替代done,fire可以替代resolve,但是想定义不同的命名,为了区分每个命名对应的是哪个cb,所以创建一个关系出来,这种关系可以使得当调用resolve时,可以确保调用的是cb1.fire,调用done时,确保调用的是cb1.add,当调用reject时,确保调用cb2.fire,调用fali时,确保调用的是cb2.add,其实说到底只是不同的触发管理不同的函数集合而已,为什么需要once,很显然,当dfd.resolve()之后,状态已经变化,此时再次调用,就不能够在触发,但是dfd.done是可以直接触发,promise和deferred两个对象,作用包含不同的功能

 

  b:state方法,无需解释,always方法,传入的参数未定,一个函数,一个数组都可能,因为不论触发dfd.reject / dfd.resole都要触发always中添加的回调,说明always实现的需求是向cb1的list中,cb2的list中都添加相同的回调,(这里有个插曲:我的思想固化问题,原以为deferred.done方法调用的是add,而add中返回的this是callbacks中的self,如果deferred.done = self, 那么调用的时候deferred.done.add(此时this指向的是self), 但是最初是把deferred.done=self.add,是把函数给了done,那么done执行的时候,就是执行add,this指向的就是deferred这个对象, promise方法,为了把promise对象的所有方法合并到deferred上

 

   c: promise与deferrd两个对象的形态,通过调用promsie.promise方法将两个对象合并,deferred这个对象会拥有done fail progress

  d: 对于数组遍历为了达到一种效果,把add方法挂载到promise上,把fire方法挂载到deferred上,通过list = tuple[2]获取resolve的cb对象,获取对应的状态(细节:对于statestring来说,遍历一遍后,state是如何保证变量的值,这里就是利用闭包特性,each工作原理肯定是传入回调函数在,在for循环时候,调用回调,每次循环都会调用一次回调,所以会生成三个函数作用域环境,每个作用域环境中都保存的各自的statestring状态,只是state是全局变量而已),list.add是把函数给了promise下的relove,此时add这个函数中的this默认指向的是promise对象,当调用resolve时,先修改状态,然后丧失reject功能,锁住notify,然后最后调用当前的回调函数

    如果调用resolve,那么调用rejecet是无效的,因为被disable,但是对于notify来说,只是lock,如果后期dfd.progress还是会继续触发

    最开始我写的时候deferred[tuple[0]] = list.firewith,firewith可以指明context的,把它封装成一个函数,在内部调用list.firewith方法,但是可以修改context指向

    deferred.fire() => deferred.firewith() 此时this指向的是deferred对象,但是当this指向deferred的时候,修改指向promise对象

    deferred.fire.call(window) => deferred.firewith() 此时this指向的是window对象   

 

   7: 关于progress为何要lock,而不是disable,考虑以下场景:当执行notify时,代表一直进行中,当调用resolve时,此时lock代表进行中不能再次触发,但是再次调用progress又能主动触发

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-07-28 19:36  IT_菜霸  阅读(45)  评论(0)    收藏  举报