promise
一.概念
Promise 是ES6对异步编程的一种解决方案,比传统的解决方案(如回调函数和事件)更合理更强大.Promise 简单说就是一个容器,里面保存着一个尚未完成且预计在未来完成的异步操作
Promise是一个构造函数,用来创建一个Promise对象.
var promise=new Promise();
Promise对象代表一个异步操作,有三种状态
pending(进行中)
fulfilled(已成功)
rejected(已失败)
改变Promise对象的状态,有两种可能:
pending变为fulfilled
pending变为rejected
一旦状态改变,就不会再变,任何时候都可以得到这个结果.
二.Promise对象
1.回调地狱
回调函数一个嵌套一个,先执行这个外层的,然后在里层一层一层的去执行
$.ajax({
type: "get",
url: '',
data: {},
success: function () {
$.ajax({
type: "get",
url: '',
data: {},
success: function () {
$.ajax({
type: "get",
url: '',
data: {},
success: function () {
$.ajax({
type: "get",
url: '',
data: {},
success: function () {
}
});
}
});
}
});
}
});
看上面代码,恶不恶心?但是以前我们必须使用这种方式才能得到我们想要的.
2.Promise使用
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,解决了回调地狱!
const promise = new Promise(function (reslove, reject) {
if(/*异步操作成功*/){
reslove('成功');//从pending变为fulfilled
}
else{
reject('失败');//从pending变为rejected
}
});
Promise是一个构造函数,接受一个函数作为参数,被称为执行器(executor),该函数的两个参数分别是reslove和reject
reslove和reject是两个函数,由Javascript引擎提供,不用自己部署
2.1 reslove
reslove函数的作用是,将Promise对象的状态从"进行中"变成"成功"(即从pending变为resloved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
2.2 reject
reject 函数的作用是,将Promise对象的状态从"进行中"变为"失败"(即从pending变为rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去
2.3 then()
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数
promise.then(function (value) {
//success
}, function () {
//error
});
Promise实例的then方法:
第一个参数是resolved状态的回调函数
第二个参数(可选) 是rejected状态的回调函数(`也就是说捕获异常还可以通过then方法的第二个参数,但是一般不建议使用,直接使用catch捕获即可)
最后返回的是一个新的Promise实例
2.4 catch()
Promise的实例方法catch:用于指定发生错误时的回调函数
promise.catch(function (msg) {
console.log(msg);
});
在Promise对象中:
如果该对象状态变为resolved,则会调用then()方法
如果该对象状态变为rejected,也就是异步操作抛出错误.则会调用catch()方法,另外,在then()里面抛出的异常,也会被catch()捕获
如果Promise状态已经变成resolved,再抛出异常错误是无效的
const promise = new Promise(function (reslove, reject
reslove('成功');
throw new Error();
});
promise.then(function (msg) {
console.log(msg);
//success
}, function (msg) {
console.log(msg);
//error
});
promise.catch(function (msg) {
console.log(msg);
});
上述代码,Promise在resolve语句后面,再抛出异常,不会被捕获,因为Promise的状态一旦改变,就永久保持该状态.
Promise对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止.所以,有这样的冒泡性质,就不需要在每个Promise对象中单独捕获异常了.
2.4.1 catch()本质
Promise.prototype.catch = function(fn){
return this.then(null,fn);
}
其实catch的本质还是then()这个方法,只不过进行了封装,一个语法糖而已.
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名
2.5 then()第二个函数和catch()区别
then()第二个参数:Promise进入失败状态,或内部执行错误
catch()可以捕捉到进入成功状态的函数内部错误
const promise = new Promise(function (reslove, reject)
throw new Error();
reslove('成功');
});
promise.then(function (msg) {
console.log(msg);
//success
}, function (msg) {
console.log("then()第二个函数",msg);
//error
}).catch(function (msg) {
console.log("catch方法",msg);
});
上面这段代码,我在Promise中抛出一个错误
then的第二个参数和catch捕获错误信息的时候会就近原则,如果是promise内部报错,reject抛出错误后,then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会捕获到。
const promise = new Promise(function (reslove, reject) {
throw new Error();
reslove('成功');
});
promise.then(function (msg) {
console.log(msg);
//success
}).catch(function (msg) {
console.log("catch方法",msg);
});
如果then()的第二个参数不存在,则会直接被catch()捕获!
当then()的第二个参数和catch同时存在时,还取决于Promise内部:
如果是reject抛出错误,只有then第二个参数能捕获
如果是resovle抛出成功,那么then的第二个参数不能捕获到,只有catch()才能捕获到!
const promise = new Promise(function (reslove, reject) {
//reslove('成功');
//reject('失败');
});
promise.then(function (msg) {
throw new Error();
console.log(msg);
},function(msg){
console.log("then方法",msg);
}).catch(function (msg) {
console.log("catch方法",msg);
});
为什么说要推荐使用catch()方法,不推荐使用then()方法的第二个函数呢?
因为使用catch()方法可以捕获到前面then()方法里执行中的错误,也更接近同步的写法(try/catch),所以,建议总是使用catch()方法,而不是使用then()的第二个参数
promise
.then(function (data) {
// success
}, function (err) {
// error
});
promise
.then(function (data) {
// success
})
.catch(function (err) {
// error
});
```