同步更新博客: www.cnblogs.com/GerryOfZhon…
同步更新专栏: zhuanlan.zhihu.com/zhongqiang
同步更新github: github.com/GerryIsWarr…html
半年不迭代,迭代搞半年,说的就是我,这里有点尴尬了,直接进入主题吧webpack
我记得在这篇博客的时候集成了Promise的,不过那个时候就简简单单的写了一点最基础,在一些特殊的case上,仍是有点问题的,因此才有了这个博客。在拜读了w3c和PromiseA+规范以后,从头至尾详细的了解了Promise这个东西,而后本身亲手写了一个和es6文档拥有相同功能的库。git
promise是一个对象,表示单个异步操做的最终结果。程序员
任何一门技术都不是一个“万金油”,只有在它最合适的场地出现,才是实现它最大价值的地方,so,Promise同样逃不过这个“真香”定律。es6
即便在已经履行或被拒绝以后也能够订阅,当某些事情只发生一次,而且做者常常想要在它已经发生以后观察它的状态github
图像,字体等资源的加载loaded属性,这个属性仅在资源彻底加载是才会实现,不然拒绝web
任何一个可能不止一次发生的事件,都不是one-and-done模型的ajax
大的流数据,分步处理流数据,而无需将流的所有内容缓冲到内存中。npm
这里有个w3c组织搞出来的一个指南--Writing Promise-Using Specifications,建议你们拜读一下,虽然没有详细讲解规范,可是对于Promise使用场景和特性作了一次详细的介绍,包括我上面说的使用场景等等。
promise
Promise自己是一种社区规范--Promises/A+,由Promise A+组织进行制定,它们提供了一个大纲和指导性的方案,只要能实现其所列规范,均可以视做实现了Promise A+,so,后面的各类变种啊,什么样的功能,均可以根据本身所需去设计,可是基础的方案按照A+ 组织规范实现就能够。
这个大纲比较啰嗦、枯燥、无味,so,咱们靠3张我画的图去理解一下Promise
实例化Promise的时候(定义内部状态的初始值等等),在同步状态下,首先会执行初始化代码,好比:new Promise((res,rej)=>{ console.log('这里就是初始化代码') }),而后再执行then方法。这个执行顺序在promise下是错误的,由于在实例代码中会首先改变Promise状态,可是前置的callback尚未在then方法中注入,因此要作推迟实例代码(setTimeout,能够将任务推到执行周期以后,宏任务),让then先跑起来,注入状态变动须要的前置依赖。
在Promise规范中定义了,then方法,必须返回一个Promise,so,Promise2就是then的返回值。而后then的动做就是将全部须要前置依赖的回调函数,Promise状态,状态变化的value全都存储起来。
等待推迟的实例代码(官方叫:异步)执行以后,触发了Promise状态的变化这个动做,而后去改变内部定义的状态,以及状态变化所要执行的操做。
内部状态已经变化完成,可是return的Promise2状态仍是pending,因此咱们须要将自身的Promise和Promise2的状态进行同步以及是否可then的持续操做。
以上为Promise的总体流程思路,它就是这样跑起来的。不过知道这个流程之后,仍是只知其一;不知其二的,下面咱们就对核心方法then进行详细剖析。
then方法须要分3个状态去解析
a. 首先实例化执行then方法,这个时候初始化的内部状态都是pending,这个时候,咱们要作一个订阅和发布的设计,将then传入的resolve和reject的回调进行包装和存储,并订阅触发动做。(这边的包装是由于订阅的时候,不只仅只是执行回调函数,还须要处理promise2的状态同步问题)
b. 在等待出发的状态的时候,这个时候状态没有变动,因此仍是keep pending状态,而promise2也是pending;当promise触发了resolve,这个时候就须要处理以前订阅的回调了,先改变Promise自身的状态,而后调用callback,将callback的值传入解析函数,同步改变Promise2的状态;触发reject动做和resolve同样
c. 这样,在整个pending链路上,自身状态和promise2状态全都同步改变完成
a. Promise内部状态以及变动完毕,内部会存储PromiseValue的值,直接获取PromiseValue的值做为参数,调起then方法传进来的resolveCallback的函数。
b. 使用同步解析函数,去同步改变Promise2的状态,以及后续可then的操做
该状态操做,同resolve操做,只是变动状态不同
以上为then方法的全部操做流程,pending的时候最特殊,有个订阅发布设计来改变自身状态,而后同步改变Promise2的状态。其余resolve和reject,都是状态已经变动完毕,直接取状态变动的值,处理回调,而后同步改变Promise2的状态值。这边同步变动Promise2的规则,在A+的规范里是有定义的。
x表明callback的返回值,首先判断x和Promise2是否相等,相等抛出TypeError的错误(毕竟若是返回值x和Promise2是一个对象的话,那操做就没啥意义了)
判断x是不是Promise对象,若是是的话,说明x是可支持then的,而后根据x的状态进行操做和同步改变Promise2的值,pending就等待执行结束,resolve和reject就分别改变Promise2的状态
若是x不是Promise对象,判断x是不是对象或者function,否的话直接resolve Promise2状态。若是是的话,try-catch捕获,定义then = x.then是否报错,若是报错则reject掉Promise2状态。
判断then是不是function,若是是则执行then操做,若是then方法执行了reject,则reject掉Promise2。
若是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。回过头来发现,最值得佩服的是这种规范的设计思惟,经过一种设计思惟,将简单的技术化腐朽为神奇。因此,我的意见,程序员的进阶,最重要的不是代码的熟练度,而是思惟的进阶。熟练度这个是每一个人均可以靠时间堆积出来的,可是更高级的工程师,应该能从总体的视角去了解,而后规划和设计,将简单的技术化神奇,将复杂的问题化简单。
替换以前有问题的createPromise的代码
将get、post、postForm,obtainBlob,upload进行改造,改方法返回都是Promise(考虑这些都是one-and-done模型,而轮询和大文件切割上传2个方法是持续性操做,因此不作改变)
删除postJSON、promiseAjax方法
// mock功能
mock: {
isOpen: true,
mockData: {}
},
复制代码
// 全局配置
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的值
完成http其余协议,put、delete等等
npm的包面向现代化,去除各类polyfill和一些兼容代码
配置webpack自动打包压缩
探索通讯和其余技术的结合玩法
等等...