JS是单线程执行了,经过event loop实现了非阻塞的I/O。编程中常常用异步回调函数的方式处理I/O的反馈结果(网络请求,用户交互事件)。如分别发送两个请求:html
function xhrRequest(url, callback) { setTimeout(function(){ // 用setTimeout模拟异步请求 callback(); }, 0) } xhrRequest('/index', function(){ console.log('request /index done'); }) xhrRequest('/list', function(){ console.log('request /list done'); })
但若是想在请求index后再请求list怎么办呢?,可能会这样写:es6
xhrRequest('/index', function(){ console.log('request /index done'); xhrRequest('/list', function(){ // 回调函数里,再次回调 console.log('request /list done'); }) })
可是若是有3个或4个异步请求有前后依赖怎么呢?回调函数会一直嵌套回调函数(callback hell),代码看起来乱糟糟的,而且很差维护。事件模式也不能很好处理这些,急需其余能下降异步编程复杂性的方式。编程
Promise已是个标准了,最新的是Promise A+标准。标准中给Promise的定义是:"A promise represents the eventual result of an asynchronous operation"。即Promise表示一个异步操做的最终结果。主要经过Promise对象的then方法和Promise对象进行交互:注册失败,成功回调函数,而且失败回调函数接收一个失败缘由(reason)参数,成功回调函数接收一个值(value)参数。Promise A+标准主要是定义then方法的规范。segmentfault
Promise对象有三种状态:Pending(待定),Fullfilled(已完成),Rejected(已拒绝)。
A:Pending的Promise对象能够转成Fullfilled或者Rejected
B:Fullfilled的Promise对象不能转成其余状态,而且必须含有一个值(value),该值不能变。
C:Rejected的Promise对象不能转成其余状态,而且必须含有一个缘由对象(reason)表示失败的缘由,该值不能变。promise
then方法的规范不少,认真读读标准。但要主要下面几点:
A:每一个回调函数只能执行一次。
B:屡次调用then方法,能够注册多个回调函数,回调函数的调用顺序取决于调用then方法的顺序。若是Promise对象已经处于fullfilled/ rejected状态,调用then方法会当即执行onfullfilled/onRejected回调函数。
C:then方法必须返回个Promise对象: Promise2 = Promse1.then(onFullfilled, onRejected)。但没规定Promise1和Promise2是否相等,这个要看具体的实现了。网络
then方法返回一个Promise对象,这样就构成一个then链。前面的Promise对象的状态变化对后面的Promise对象的状态的影响称为Promise解决程序(The Promise Resolution Procedure)。框架
实现Promise标准的库和框架有不少了,jQuery,Zeptojs,ES6等。好多库中Promise实现叫Deferred,Deferred对象是用来操做Promise对象(修改Promise对象状态),而Promise对象自己只提供then方法添加回调函数(以及其余添加回调函数的方法),不提供操做Promise对象的方法,这样设计使得Promise对象对外不可修改,详细参考ZeptoJS Deferred实现。异步
Promise是把相似的异步处理对象和处理规则进行规范化, 并按照采用统一的接口来编写,而采起规定方法以外的写法都会出错。这样更有利理解,维护。将复杂的异步处理轻松地进行模式化。async