同步更新博客: www.cnblogs.com/GerryOfZhon…
同步更新专栏: zhuanlan.zhihu.com/zhongqiang
同步更新github: github.com/GerryIsWarr…

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

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

什么是promise?

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

什么时候使用?

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

  1. one-and-done操作模型

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

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

  1. 更多状态的变化

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

不建议使用promise的场景

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

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

Tips

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



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

Promise本身是一种社区规范--Promises/A+,由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状态全都同步改变完成

  1. resolve 状态

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

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

  1. 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。回过头来发现,最值得佩服的是这种规范的设计思维,通过一种设计思维,将简单的技术化腐朽为神奇。所以,个人意见,程序员的进阶,最重要的不是代码的熟练度,而是思维的进阶。熟练度这个是每个人都可以靠时间堆积出来的,但是更高级的工程师,应该能从整体的视角去了解,然后规划和设计,将简单的技术化神奇,将复杂的问题化简单。

代码可以到 github 上查看,功能完善了,支持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地址:github.com/GerryIsWarr… 对你有帮助或启发,点个小星星,支持继续研究下去

转载于:https://juejin.im/post/5cb982e4f265da0368145788

前端通信:ajax设计方案(十)--- 完善Promise A+规范,增加mock数据功能相关推荐

  1. 云e办学习笔记(二十五)导入导出Excel表数据功能实现

    前言 本系列博客基于B站的云e办管理系统,前端和后端我都自己敲了一遍,这里做一个学习记录.云e办的原始视频链接如下:https://www.bilibili.com/video/BV1Ai4y1P7T ...

  2. 前端简单入门第十八讲 使用jQuery实现表格的隔行换色

    还记得之前我使用JavaScript来实现表格的隔行换色效果吗?如果读者初次翻阅本文,可记得看看前端简单入门第十二讲 使用JavaScript完成后台数据展示表格的隔行换色!现在我就来使用jQuery ...

  3. 前端通信:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码(改迭代已作废,移步迭代10)...

    该迭代已作废,最新的请移步这里:https://www.cnblogs.com/GerryOfZhong/p/10726306.html 距离上一篇博客书写,又过去了大概几个月了,这段时间暂时离开了这 ...

  4. 前端通信:ajax设计方案(三)--- 集成ajax上传技术

    在此之前让我感慨一下现在的前端开发的氛围.我遇到好多人,给我的观念都是,这个东西这个框架有了,那个东西那个框架做了,前端嘛,学几个框架,这个拼凑一下那个拼凑一下就好了.其实我想问,东西都框架做了,那你 ...

  5. 2022前端知识整理:十、vue基础

    十.vue基础 2022前端知识整理:第十部分.vue基础,仅包含vue2.0相关知识,建议先完成html5.css3和JavaScript ES6之后再学习.部分图片未上传成功,稍后完善,请见谅. ...

  6. ajax 取值 返回map_springboot|前端发ajax请求到后台Controller及常见的坑

    前端发ajax请求 这块是web的基础,发web请求大概需要以下几步1.引用web相关的依赖2.前端页面引入jquery.js3.编写ajax请求4.编写对应的Controller 引入web相关的依 ...

  7. 【零基础学Java】—TCP通信(五十四)

    [零基础学Java]-TCP通信(五十四) TCP通信:面向连接的通信,客户端和服务器端必须经过三次握手,建立逻辑连接,才能通信(安全). 通信的步骤: 服务器端先启动 服务器端不会主动的请求客户端, ...

  8. 【手写 Promise 源码】第八篇 - 完善 Promise 并通过 promise-aplus-tests 测试

    一,前言 上一篇,实现 Promise 对返回值 x 各种情况的分析和处理,主要涉及以下几个点: 回顾了相关的 Promise A+ 规范内容: 根据 Promise A+ 规范描述和要求,实现了核心 ...

  9. 新年新气象!新益求新的前端周刊(第十四期)

    前端周刊是一份专为前端从业人员,以及对前端.设计领域感兴趣的朋友们打造的技术周刊.程小狮会精选出前端.设计领域近期相关的资讯.热点以及技术干货,与大家一同分享. 前端周刊专注于前端领域技术分享.希望这 ...

最新文章

  1. L1-044 稳赢 (暴力法)
  2. Java实现的简单神经网络(基于Sigmoid激活函数)
  3. php curl 下载网页,php 通过cURL函数抓取网页、下载网页的简单示例
  4. BugKuCTF 杂项 telnet
  5. yarn的基本组成和工作流程
  6. php将excel导入mysql,PHP实现将EXCEL文件导入到MYSQL
  7. 树存储结构(代码、分析、汇编)
  8. 一位准程序员对软件行业的8个问题
  9. log4j.properties的配置与详细说明
  10. K8S认证、授权与准入控制(RBAC)详解
  11. 苏州netapp存储服务器维修,NetApp存储日常维护手册 v12.doc
  12. php视频系统源码,基于ThinkPHP框架仿优酷视频源码带数据,后台功能强大
  13. 表结构生成html页面,表结构设计器
  14. 步进电机驱动器单片机控制电路
  15. linux安装2870无线网卡,告诉你Ubuntu 12.04下RT5370无线网卡驱动安装的方法及命令
  16. error: Microsoft Visual C++ 14.0 is required. Get it with “Build Tools for Visual Studio“: https://
  17. 恒生UFX 统一接入介绍
  18. WinCC V7.2学习记录
  19. update与upgrade的区别
  20. STM32F1系列以及CM3内核的时钟与中断内容详解

热门文章

  1. 4.Ext JS Ext.data.Store本地过滤
  2. linux系统宿主定制之初窥门径
  3. mybatis 操作动态表+动态字段+存储过程
  4. Generic Data Access Objects -范型DAO类设计模式
  5. 如何使用Ajax技术开发Web应用程序(2)
  6. 扩展SpringMVC以支持绑定JSON格式的请求参数
  7. 线程基类的构建与代码实践
  8. linux内存源码分析 - 内存压缩(同步关系)
  9. php 不等待返回的实现方法(异步调用)
  10. Exchange 2010 OAB下载问题排错error 0x80200049