1.Promise简介
什么是promise
Promise是异步编程的一种解决方案,它的构造函数是同步执行的,then 方法是异步执行的。
为什么使用Promise
在JavaScript的世界中,所有代码都是单线程执行的。但是,很多网络操作,浏览器事件,都必须是异步执行,以保证软件的执行效率,毕竟如果用户发一个请求,网站在请求期间直接卡住,用户什么操作都做不了,是一个很糟糕的体验。异步f方法执行后的同步处理可以用回调函数实现,回调函数形式如下:
function callback() {
console.log('Done');
}
doSometing(){
.....
callBack()
}
但是这样存在一个问题,比如我们先要向服务器请求数据A,得到A后,再通过A向服务器请求B,得到B后还需要得到C,最后才能真正用C来处理我们的数据,这时候就会有三层回调!
getA(function(A) {
getB(A, function(B) {
getC(B, function(C) {
console.log('得到最终结果: ' + C);
}, failureCallback);
}, failureCallback);
}, failureCallback);
阅读上面代码,是不是很难受,上述形成了经典的 回调地狱。Promise就是用来处理这样的问题的。现在用promise来重写写这样的逻辑:
getA().then(function(A) {
return getB(A);
})
.then(function(B) {
return getC(B);
})
.then(function(C) {
console.log('得到最终结果: ' + C);
})
.catch(failureCallback);
这样是不是变得清晰很多啦!
我们可以发现,promise的链式操作减低了编码难度,代码可读性明显增强。
promise中的状态
promise对象仅有三种状态
pending(进行中)
fulfilled(已成功)
rejected(已失败)
pedding(初始状态):调用promise时,一开始就呈现出等待状态,遇到resolve或者reject之前,都处于这个状态,且可以改变,但如果确定了状态(fulfilled/reject),则结果将永远不变,不能再次修改
fulfilled(成功状态):在执行了resolve后,promise则会从pedding变成fulfilled,后续会进入.then 的回调函数中,在回调函数的第一个参数函数中可以获取到值
rejected(失败状态):在执行了reject后,promise状态会变成rejected,rejected函数传递的参数,可以在.then的第二个参数函数中获取的到,或者是在.catch获取到,但是如果程序上的错误,得通过.catch函数去拿到失败消息,在.then中是获取不了的
认真阅读下图,我们能够轻松了解promise整个流程
2.Promis的用法
Promise对象是一个构造函数,用来生成Promise实例:
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。
resolve:用于创建一个成功状态的Promise对象,可以之间在.then的成功回调中,获取resolve的值。
const p = Promise.resolve("成功");
p.then((res) => {
console.log("----打印:", res); //----打印: 成功
});
//该用法类似于
const p1 = new Promise((resolve, reject) => {
resolve("成功");
});
p1.then((res) => {
console.log("----打印:p1", res); //----打印:p1 成功
});
//后续代码中都会出现类似,或者另外中写法,尝试的时候,不能同时放出来执行
reject:这个方法跟Promise.resolve一样,只是作用不同,属于拒绝的状态;可以直接在.then的失败回调中,获取reject的值;也可以在.catch中获取;如果两者同时出现代码中,看看是catch写在前面还是.then函数写在前面 —业务中,拒绝状态用.then去执行回调,异常用.catch
const p = Promise.reject("失败");
p.then(
(res) => {
console.log("----打印:", res); //不执行
},
(rej) => {
console.log("----打印:", rej); //----打印: 失败
}
);
//另外写法
p.then(
(res) => {
console.log("----打印:p", res); //不执行
},
(rej) => {
console.log("----打印:p", rej); //----打印:p 失败
}
).catch((error) => {
console.log("----打印:catch", error); //不执行
});
//另外写法---基本没有吧catch写在第一个
p.catch((error) => {
console.log("----打印:catch", error); //----打印:catch 失败
}).then(
(res) => {
console.log("----打印:p", res); //不执行
},
(rej) => {
console.log("----打印:p", rej); //不执行
}
);
//另外写法
p.then((res) => {
console.log("----打印:p", res); //不执行
}).catch((error) => {
console.log("----打印:catch", error); //----打印:catch 失败
});
//该用法类似于
const p1 = new Promise((resolve, reject) => {
reject("失败");
});
p1.then(
(res) => {
console.log("----打印:p1", res); //不执行
},
(rej) => {
console.log("----打印:p1", rej); //----打印:p1 失败
}
);
另外,Promise构建出来的实例存在以下方法:
- then()
- catch()
- finally()
then():
then是实例状态发生改变时的回调函数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
catch:
catch()方法是 .then(null, rejection) 或 .then(undefined, rejection) 的别名,用于指定发生错误时的回调函数.
getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
finally()
finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});