promise规范
purplebamboo opened this issue · comments
promise规范
promise最早是在commonjs社区提出来的,当时提出了很多规范。比较接受的是promise/A规范。后来人们在这个基础上。提出了promise/A+规范,也就是实际上的业内推行的规范。es6也是采用的这种规范。
promise/A规范在这里
不过规范这种东西看着比较晦涩。下面具体说说promise的用法。
##规范里的定义
什么是promise呢,说白了就是一个承诺,我承诺你叫我做的事情我将来会去做,不过要等我能去做的时候。
一个promise对象有三种状态,预备状态(pending),成功态(fulfilled),失败态(rejected)。
我们看下promise对象的构造函数:
var promise = new Promise(function(resolve, reject) {
//if(报错){
//reject(new Error('promise出错啦。。'))
//}
//某个异步操作,比如ajax请求
setTimeout(function(){
resolve('异步请求结束了。。变成完成态')
},1000)
});
promise对象初始状态一般是预备状态,并且promise对象的状态转换只能是预备状态到成功态或者预备状态到失败态。
- resolve会将promise转变为成功态。
- reject会将promise转变为失败态。
##promise对象的then方法
我们可以使用promise对象的then方法往这个对象里面添加回调函数。调用方式为:
promise.then(onFulfilled, onRejected)
then接受一个成功回调,还有失败回调。都是可选参数。
当promise对象是预备状态这些函数不会立即执行。而是等待。
当promise对象变成了成功态会调用onFulfilled,参数为resolve传递的值。
变成失败态则会调用onRejected,参数为reject传递的值。
因为then返回一个promise对象。所以支持链式调用:
promise.then(onFulfilled, onRejected).then(onFulfilled, onRejected)
then负责往promise对象里添加函数,随便添加多少。
- 如果promise对象处于预备状态就等待。一直到改变状态才开始执行。
- 如果promise对象已经处于结束态(成功或者失败)再用then添加回调就直接调用对应的回调。
- 此外前一个onFulfilled函数的返回值如果不是promise。会作为下一个onFulfilled的参数。onRejected类似。
例子:
//onRejected可以为null也可以省略
promise.then(function(prevValue){
console.log('resolve的值:'+prevValue)
return "我是传递给第二个回调的参数"
},null).then(function(value){
console.log('报告:'+ value)
console.log('我是最后一个')
})
/*
*结果
resolve的值:异步请求结束了。。变成完成态
报告:我是传递给第二个回调的参数
我是最后一个
*/
可以看到一直等到前面的异步操作结束了,后面的才会执行。
此外如果onFulfilled返回一个新的promise对象,那么之后的then添加的操作函数会被托管给新的promise对象。然后之后的操作函数执不执行就由新的promise对象说了算了。
比如:
promise.then(function(prevValue){
console.log('resolve的值:'+prevValue)
var newPromise = new Promise(function(resolve,reject){
setTimeout(function(){
resolve('2秒后,新的promise变成完成态')
},2000)
})
//返回新的promise
console.log('返回一个promise,开始托管。')
return newPromise
},null).then(function(value){
console.log('报告:'+ value)
console.log('我是最后一个')
})
/*
*结果
resolve的值:异步请求结束了。。变成完成态
返回一个promise,开始托管。
报告:2秒后,新的promise变成完成态
我是最后一个
*/
##promise对象的catch方法
用来捕获上一个then方法里面reject过来的错误,说白了就是一种特殊的then
promise.catch(function(error) {
console.log('发生错误!', error);
});
//等价于
promise.then(null,function(error) {
console.log('发生错误!', error);
});
##Promise的类方法resolve和reject
Promise.resolve
接受的参数如果是promise对象就直接返回。
如果是一个非promise,但具有then方法的对象就会尝试转换成一个成功状态的promise对象。
如果是个不具有then方法的值就传递给下一个onFulfilled函数,并且生成一个处于成功状态的promise对象。
Promise.reject
接受的参数如果是promise对象就直接返回。
如果是一个非promise,但具有then方法的对象就会尝试转换成一个失败状态的promise对象。
如果是个不具有then方法的值就传递给下一个onRejected函数。并且生成一个处于失败状态的promise对象。
var a = Promise.resolve(true)
//same as
var a = new Promise(function(resolve,reject){
//立即变成成功状态
resolve(true)
})
var b = Promise.reject(true)
//same as
var b = new Promise(function(resolve,reject){
//立即变成失败状态
reject(true)
})
//使用Promise.resolve转换不标准的jQuery的promise对象
var promise = Promise.resolve($.get('http://www.taobao.com'));
##Promise的类方法all和race
Promise.all用来包装一系列的promise对象返回一个包装后的promise对象,比如我们称之为A。
- 当所有的promise对象都变成成功状态(fulfilled)后。这个包装后的A才会把自己变成成功态。A会等最慢的那个promise对象变成成功态(fulfilled)后把自己变成成功态。
- 只要其中一个promise对象变成失败态(rejected),包装后的A就变成rejected,并且第一个rejected传递的值,会传递给A后面使用then添加的onRejected回调。
var a = new Promise(function(resolve,reject){})
var b = Promise.resolve(true)
Promise.all([a,b])
Promise.race也是用来包装一系列的promise对象返回一个包装后的promise对象,比如我们称之为B。跟all不同的是,只要有一个对象变成了成功状态(fulfilled),B就会变成成功状态。
Promise.race([a,b])
all是一种与的关系,而race是一种或的关系。
##Promise的类方法defer使用
其实除了在构造函数里面使用resolve,reject去改变一个promise对象的状态外,我们还有另外一种方式。那就是defer。
例子:
promise.then(function(val){
var d = Promise.defer()
setTimeout(function(){
d.resolve('2秒后,新的promise变成完成态')
//d.reject('err')
},2000)
//返回自己的promise对象
return d.promise
})
Promise.defer()
生成一个defer对象。这个对象d具有一个promise对象属性。d.resolve会把管理的promise变成完成态,同理d.reject会将管理的promise变成失败态。
整个promise的用法就说完了。
其实A+规范中只定义了then函数的具体细节,而promise状态的改变都是前人的经验慢慢积累后总结出的一套使用方式
参考链接:
1