博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端通信:ajax设计方案(十)--- 完善Promise A+规范,增加mock数据功能
阅读量:5103 次
发布时间:2019-06-13

本文共 4160 字,大约阅读时间需要 13 分钟。

半年不迭代,迭代搞半年,说的就是我,这里有点尴尬了,直接进入主题吧

我记得在的时候集成了Promise的,不过那个时候就简简单单的写了一点最基础,在一些特殊的case上,还是有点问题的,所以才有了这个博客。在拜读了w3c和PromiseA+规范之后,从头到尾详细的了解了Promise这个东西,然后自己亲手写了一个和es6文档拥有相同功能的库。

 

什么是promise?

promise是一个对象,表示单个异步操作的最终结果。

 

什么时候使用?

任何一门技术都不是一个“万金油”,只有在它最合适的场地出现,才是实现它最大价值的地方,so,Promise一样逃不过这个“真香”定律。

1. one-and-done操作模型

    • 异步I / O操作:从存储API读取或写入的方法可以返回承诺。
    • 异步网络操作:通过网络发送或接收数据的方法可以返回承诺。
    • 长时间运行的计算:需要一段时间来计算某些东西的方法可以在另一个线程上完成工作,返回结果的承诺。
    • 用户界面提示:要求用户回答的方法可以返回承诺。

2. One-Time "Events”模型

  即使在已经履行或被拒绝之后也可以订阅,当某些事情只发生一次,并且作者经常想要在它已经发生之后观察它的状态

3.更多状态的变化

  图像,字体等资源的加载loaded属性,这个属性仅在资源完全加载是才会实现,否则拒绝

 

不建议使用promise的场景

1. 任何一个可能不止一次发生的事件,都不是one-and-done模型的

2. 大的流数据,分步处理流数据,而无需将流的全部内容缓冲到内存中。

 

这里有个w3c组织搞出来的一个指南--,建议大家拜读一下,虽然没有详细讲解规范,但是对于Promise使用场景和特性做了一次详细的介绍,包括我上面说的使用场景等等。

 

以上讲的更多偏向应用层的知识点,下面就让我们深入它的根本去了解Promise是如何实现的。

Promise本身是一种社区规范--,由Promise A+组织进行制定,它们提供了一个大纲和指导性的方案,只要能实现其所列规范,都可以视作实现了Promise A+,so,后面的各种变种啊,什么样的功能,都可以根据自己所需去设计,但是基础的方案按照A+ 组织规范实现就可以。

这个大纲比较啰嗦、枯燥、无味,so,我们靠3张我画的图去理解一下Promise

 

第一张:promise整体流程图

1.  实例化Promise的时候(定义内部状态的初始值等等),在同步状态下,首先会执行初始化代码,比如:new Promise((res,rej)=>{ console.log('这里就是初始化代码') }),然后再执行then方法。这个执行顺序在promise下是错误的,因为在实例代码中会首先改变Promise状态,但是前置的callback还没有在then方法中注入,所以要做推迟实例代码(setTimeout,可以将任务推到执行周期之后,宏任务),让then先跑起来,注入状态变更需要的前置依赖。

2.  在Promise规范中定义了,then方法,必须返回一个Promise,so,Promise2就是then的返回值。然后then的动作就是将所有需要前置依赖的回调函数,Promise状态,状态变化的value全都存储起来。

3.  等待推迟的实例代码(官方叫:异步)执行之后,触发了Promise状态的变化这个动作,然后去改变内部定义的状态,以及状态变化所要执行的操作。

4.  内部状态已经变化完成,但是return的Promise2状态还是pending,所以我们需要将自身的Promise和Promise2的状态进行同步以及是否可then的持续操作。

 

以上为Promise的整体流程思路,它就是这样跑起来的。不过知道这个流程以后,还是一知半解的,下面我们就对核心方法then进行详细剖析。

 

第二张:then方法核心解析

then方法需要分3个状态去解析

1. pending 状态

  a. 首先实例化执行then方法,这个时候初始化的内部状态都是pending,这个时候,我们要做一个订阅和发布的设计,将then传入的resolve和reject的回调进行包装和存储,并订阅触发动作。(这边的包装是因为订阅的时候,不仅仅只是执行回调函数,还需要处理promise2的状态同步问题)

  b. 在等待出发的状态的时候,这个时候状态没有变更,所以还是keep pending状态,而promise2也是pending;当promise触发了resolve,这个时候就需要处理之前订阅的回调了,先改变Promise自身的状态,然后调用callback,将callback的值传入解析函数,同步改变Promise2的状态;触发reject动作和resolve一样

  c. 这样,在整个pending链路上,自身状态和promise2状态全都同步改变完成

2. resolve 状态

  a. Promise内部状态以及变更完毕,内部会存储PromiseValue的值,直接获取PromiseValue的值作为参数,调起then方法传进来的resolveCallback的函数。

  b. 使用同步解析函数,去同步改变Promise2的状态,以及后续可then的操作

3. reject 状态 

  该状态操作,同resolve操作,只是变更状态不一样

 

以上为then方法的所有操作流程,pending的时候最特殊,有个订阅发布设计来改变自身状态,然后同步改变Promise2的状态。其他resolve和reject,都是状态已经变更完毕,直接取状态变更的值,处理回调,然后同步改变Promise2的状态值。这边同步变更Promise2的规则,在A+的规范里是有定义的。

 

第三张:同步改变Promise2状态以及是否可继续then的操作

状态同步改变和是否可持续then的操作解析流程,都按照A+规范去判断

1. x代表callback的返回值,首先判断x和Promise2是否相等,相等抛出TypeError的错误(毕竟如果返回值x和Promise2是一个对象的话,那操作就没啥意义了)

2. 判断x是否是Promise对象,如果是的话,说明x是可支持then的,然后根据x的状态进行操作和同步改变Promise2的值,pending就等待执行结束,resolve和reject就分别改变Promise2的状态

3. 如果x不是Promise对象,判断x是否是对象或者function,否的话直接resolve Promise2状态。如果是的话,try-catch捕获,定义then = x.then是否报错,如果报错则reject掉Promise2状态。

4. 判断then是否是function,如果是则执行then操作,如果then方法执行了reject,则reject掉Promise2。

5. 如果then执行resolve,则将y替换掉x,重新和Promise2进行状态的同步改变。

 

PS:这里的x.then就是下面的这种状况,A+规范定义这样的返回值代表还是可then的,需要处理

temp.then(function (x) {    return {      then: function(resolve, reject) {        resolve(42);      }    }  })

 

至此整个Promise就结束了,从Promise怎么去运行,到核心代码then的处理,以及Promise2的同步改变,这就是所谓的Promise。回过头来发现,最值得佩服的是这种规范的设计思维,通过一种设计思维,将简单的技术化腐朽为神奇。所以,个人意见,程序员的进阶,最重要的不是代码的熟练度,而是思维的进阶。熟练度这个是每个人都可以靠时间堆积出来的,但是更高级的工程师,应该能从整体的视角去了解,然后规划和设计,将简单的技术化神奇,将复杂的问题化简单。

 

整个代码我就不贴出来了,太长了,可以到 上查看,功能完善了,支持all、race、resolve、reject方法

 

 

在ajax-js的库的变动,如下:

1. 替换之前有问题的createPromise的代码

2. 将get、post、postForm,obtainBlob,upload进行改造,改方法返回都是Promise(考虑这些都是one-and-done模型,而轮询和大文件切割上传2个方法是持续性操作,所以不做改变)

3. 删除postJSON、promiseAjax方法

 

ajax-js库增加新功能:mock功能

全局配置参数:

// mock功能    mock: {      isOpen: true,      mockData: {}    },

 

流程如下:

 

demo:

// 全局配置ajax.config({  baseURL:'http://localhost:3000/',  mock: {    isOpen:true,    mockData: {      'post':'我是mock数据'    }  }})// 测试代码function request_post() {  ajax.post('post',{data:'ajaxPost'})    .then(x=>{      console.warn(x)    })}

 

测试结果:

 

注意:mockData的key是url的值,不是baseUrl+url的值

 

 结束语:

ajax-js.1.9.2完成了,一直在思考还有什么需要改进的东西,之后的迭代需要走的方向

1. 完成http其他协议,put、delete等等

2. npm的包面向现代化,去除各种polyfill和一些兼容代码

3. 配置webpack自动打包压缩

4. 探索通信和其他技术的结合玩法

5. 等等...

 

github地址:   对你有帮助或启发,点个小星星,支持继续研究下去

转载于:https://www.cnblogs.com/GerryOfZhong/p/10726306.html

你可能感兴趣的文章
[leetcode]Minimum Path Sum
查看>>
Aizu - 1378 Secret of Chocolate Poles (DP)
查看>>
IO流写出到本地 D盘demoIO.txt 文本中
查看>>
Screening technology proved cost effective deal
查看>>
mysql8.0.13下载与安装图文教程
查看>>
Thrift Expected protocol id ffffff82 but got 0
查看>>
【2.2】创建博客文章模型
查看>>
Kotlin动态图
查看>>
从零开始系列之vue全家桶(1)安装前期准备nodejs+cnpm+webpack+vue-cli+vue-router
查看>>
Jsp抓取页面内容
查看>>
大三上学期软件工程作业之点餐系统(网页版)的一些心得
查看>>
可选参数的函数还可以这样设计!
查看>>
[你必须知道的.NET]第二十一回:认识全面的null
查看>>
Java语言概述
查看>>
关于BOM知识的整理
查看>>
使用word发布博客
查看>>
面向对象的小demo
查看>>
微服务之初了解(一)
查看>>
GDOI DAY1游记
查看>>
收集WebDriver的执行命令和参数信息
查看>>