介绍:
- 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果
- promise解决异步调用时的造成多层代码嵌套的问题。
- promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),一旦状态发生了改名,就不会在变。
一、基本用法
function promise() {
return new Promise(function (resolve, reject) {
//resolve的参数一般会返回一个成功的值或者是一个Promise的实例给回调函数
// reject的参数一般会返回一Error对象的实例,或者是错误提示。
// 异步代码
setTimeout(() => {
if (true) {
ref("成功值或是一个prmise的实例")
}
if (false) {
reject('错误')
}
}, 1000);
})
}
promise().then(function (value) {
console.log(value);
}, function(error){
console.log(error)
})
var p1 = new Promise(function(ref, res){
setTimeout(function(){
ref('a')
}, 1000)
})
p1.then(function(v){
console.log(v);
})
p1.then(function(v){
console.log(v);
})
//状态的不可变 两个log会同时打印出来,后面的log并不会再次延时1秒。
Api
二、 Promise.prototype.then
then方法是实现链式调用的关键,它会返回一个promise的实例。
promise().then(function(){
.....
return promise2() //指定返回一个promise实例
}).then(function(v){
.....
return promise3()
}).then(function(){
.....
})
- 后面的then会等待前一个then的promise实例发生状态的变化,才会被调用。
then的回调函数返回的值会关系到该then返回的promise的行为,具体如下:
- 如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
function ajax(){
return new Promise(function(reslove, reject){
setTimeout(function(){
reslove('成功')
}, 1000)
})
}
ajax()
.then(function(v){
console.log(v)
return 'hello' // 返回一个值
})
.then(function(v){
console.log(v) //接收到该值
})
2、如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
ajax()
.then(function(v){
console.log(v)
throw new Error('抛出一个错误'); // 抛出错误
})
.then(function(v){
console.log(v) //hello
}, function(error){
console.log(error) // 接收到这错误
})
3、如果then中的回调函数返回一个已经是接受状态的Promise,那么then返回的Promise也会成为接受状态,并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值
function ajax(){
return new Promise(function(reslove, reject){
setTimeout(function(){
reslove('成功')
}, 1000)
})
}
function ajax2(){
return new Promise(function(reslove, reject){
setTimeout(function(){
reslove('成功2')
}, 1000)
})
}
ajax()
.then(function(v){
console.log(v)
return ajax2() // 返回一个接收状态的promise
})
.then(function(v){
console.log(v) // 成功2 (接收状态的promise回调值)
})
4、如果then中的回调函数返回一个已经是拒绝状态的Promise,那么then返回的Promise也会成为拒绝状态,并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
function ajax(){
return new Promise(function(reslove, reject){
setTimeout(function(){
reslove('成功')
}, 1000)
})
}
function ajax2(){
return new Promise(function(reslove, reject){
setTimeout(function(){
reject('失败')
}, 1000)
})
}
ajax()
.then(function(v){
console.log(v)
return ajax2() // 放回一个拒绝状态promise
})
.then(function(v){
console.log(v)
}, function(error){
console.log(error) // 拒绝状态promise回调值
})
三、Promise.prototype.catch
catch是
reject
状态的别名,在链式调用的过程中如果有一个promise触发了reject
状态并且该实例没有捕获它(没有指定then的第二回调函数),catch
方法就会捕获这个错误,会跳过它promise
执行后面的promise
,catc
还会捕获运行中抛出错误。
function ajax(){
return new Promise(function(reslove, reject){
setTimeout(function(){
reject('错误')
}, 1000)
})
}
function ajax2(){
return new Promise(function(reslove, reject){
setTimeout(function(){
reslove('成功')
}, 1000)
})
}
对于上面promise函数,下面两次的错误捕获是等价的。
1、
ajax()
.then(function(v){
console.log(v)
return ajax2();
})
.then(function(){
console.log('end')
}, function(error){
console.log(error)
})
2、
ajax()
.then(function(v){
console.log(v)
return ajax2();
})
.then(function(){
console.log('end')
})
.catch(function(error){
console.log(error)
})
-
catch捕获机制
function p(){
return new Promise(function(resolve, reject){
setTimeout(() => {
resolve('成功')
}, 1000)
})
}
function p2(){
return new Promise(function(resolve, reject){
setTimeout(() => {
reject('错误p2')
}, 1000)
})
}
function p3(){
return new Promise(function(resolve, reject){
setTimeout(() => {
resolve('成功')
}, 1000)
})
}
p()
.then(function(v){
console.log(v)
return p2()
})
.then(function(v){
console.log(v)
return p3()
})
.then(function(v){
console.log(v)
})
.catch(function(error){
console.log(error + 'b');
})
.then(function(){
console.log('end')
})
// 成功
//错误p2
// end
catch一样会返回一个
promise
实例。注意catch只会捕获在它前面的promise
实例,它后面的promise
实例与它无关。