Promise接口
es6将Promise写入语言标准,因此目前js原生支持Promise对象。使用Promise的优点就不赘述了,Promise对象起到一个代理的作用(proxy),它充当异步操作和回调函数之间的中介。它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立即返回,所以和同步流程没有区别。Promise对象使用then方法添加回调函数。then方法可以接受两个回调函数,第一个是异步操作成功时的回调函数,第二个是异步操作失败时的回调函数(可以省略)。一旦状态改变,就调用相应的回调函数。(Promise的构造函数内容下面会细讲)
new Promise(...).then(
fn1,
fn2
)
上面代码中,Promise对象使用then方法绑定两个回调函数:操作成功时的回调函数fn1,操作失败时的回调函数fn2。这两个函数都接受异步操作传回的值作为参数。如果把这两个函数复杂化一点,伪代码就是这样
new Promise(...).then(function(value){
... // 逻辑代码
console.log(value);
}, function(error){
... // 逻辑代码
console.log(error);
})
接下来我们来看一下Promise的具体应用例子
Promise对象生成
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由js引擎提供,不用自己部署。
var promise = new Promise(function(resolve, reject){
//异步操作代码
if(...){
//resolve函数有两个作用,第一个是将这个对象的异步操作状态改为成功,第二个是将参数value传入回调函数
resolve(value);
} else {
//reject函数有两个作用,第一个是将这个对象的异步操作状态改为失败,第二个是将参数error传入回调函数
reject(error);
}
})
这里的value和error,是promise对象传给回调函数的参数,如果成功则传value,失败传error,所以
var promise = new Promise(function(resolve, reject){
resolve('success')
})
promise.then(function(value){
console.log(value) // 'success'
})
失败的时候
var promise = new Promise(function(resolve, reject){
reject('error')
})
promise.then(function(value){
console.log(value) //不执行,第一个函数是成功的函数
}, function(error){
console.log(error) // 'error'
})
当然这里为了方便理解把错误处理函数写在了then中
链式调用
我们要注意,每一次调用then函数之后,返回的还是一个Promise对象
var promise1 = new Promise(function(resolve, reject){
resolve('success') //省略其他逻辑代码
})
promise1
.then(function(value){
console.log(value) // 'success'
return 'success'
})
.then(function(value){
console.log(value) // 'success'
})
这里第一个then直接返回success,相当于
var promise1 = new Promise(function(resolve, reject){
resolve('success') //省略其他逻辑代码
})
var promise2 = new Promise(function(resolve, reject){
resolve('success') //省略其他逻辑代码
})
promise1
.then(function(value){
console.log(value) // 'success'
return promise2;
})
.then(function(value){
console.log(value); // 'success'
})
也就是说如果直接在then中return,相当于这个Promise对象的状态改为了已完成,并且把return的值传入了回调函数中。那么如果没有return一个值,那么下一个then函数自然是拿不到的
promise1
.then(function(value){
return;
})
.then(function(value){
console.log(value); // 'undefined'
})
那么如果发生了错误呢
new Promise()
.then(step1)
.then(step2)
.then(step3)
.then(
console.log,
console.error
);
如果step1出错,返回的Promise对象状态为rejected,接下来的step2就不会再执行了,Promises对象开始寻找,接下来第一个操作失败时的回调函数,于是它找到了console.error,当然推荐的写法是
promise
.then(function(data) {
// success
})
.catch(function(err) {
// error
});
catch方法可以捕获前面then方法执行中的错误,也更接近同步的写(try/catch) 需要注意的是,catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。
Promise的一次性
Promise的变化途径只有两种。
- 异步操作从未完成到已完成
- 异步操作从未完成到失败
这种变化只能发生一次,一旦当前状态变为“已完成”或“失败”,就意味着不会再有新的状态变化了,所以在Promise中重复调用resolve和reject没有作用
var promise = new Promise(function(resolve, reject){
resolve(...)
resolve(...) // 不起作用
})