开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
前言
在ES6中有一个非常好用且重要的特性Promise,什么是Promise,Promise是用来做什么的?Promise其实是在js里异步编程的一种解决办法
那我们什么时候会用Promise处理异步事件呢?一种很常见的场景就是网络请求,当我们封装了一个网络请求,不能立即拿到结果,往往我们会传到另一个函数,在数据请求成功的时候,将数据通过传入的函数回调出去,当网络请求非常复杂的时候就会出现回调地狱
回调地狱
例如当我们通过ajax请求一个地址,成功之后继续进行另一个ajax请求,成功之后再继续进行下一个ajax请求直到最后一个请求结束,这就是回调地狱,这样的代码写起来复杂,不容易维护,而Promise可以以一种非常优雅的方式来解决这个问题
$.ajax({
url,
type:'GET',
success:function(res){
$.ajax({
url,
type:'GET',
success:function(res){
$.ajax({
url,
type:'GET',
success:function(res){
$.ajax({
url,
type:'GET',
success:function(res){
console.log(res);
}
})
}
})
}
})
}
})
Promise解决回调地狱
使用setTimeout模拟异步事件,log模拟返回的结果
setTimeout(() => {
console.log('模拟异步事件');
}, 1000);
我们对异步操作进行封装,封装成Promise代码,Promise是一个类,通过这个类new一个对应的对象,在new Promise的时候要求传入一个函数,函数本身里面有两个参数,一个是resolve,另一个是reject
resolve是解决的意思,而reject是拒绝的意思,resolve和reject本身也是一个函数
将异步操作封装进Promise里,当异步操作完成后调用resolve(),就会在Promise的最外面执行一个叫then的方法,在里面返回结果。然后继续return一个new Promise,在里面继续执行异步操作,异步操作完成后调用resolve(),继续执行Promise的最外面的then方法,一直到结束
这样一来就清晰很多了,解决了回调地狱的问题,将嵌套的代码变成了链式编程
new Promise((resolve,reject)=>{
//第一次网络请求
setTimeout(() => {
resolve()
}, 1000);
}).then(()=>{
//第一次拿到结果
console.log('模拟异步事件1');
return new Promise((resolve,reject)=>{
//第二次网络请求
setTimeout(() => {
resolve()
}, 1000);
})
}).then(()=>{
//第二次拿到结果
console.log('模拟异步事件2');
return new Promise((resolve,reject)=>{
//第三次网络请求
setTimeout(() => {
resolve()
}, 1000);
})
}).then(()=>{
//第三次拿到结果
console.log('模拟异步事件3');
})
Promise的三种状态
Promise在执行异步操作之后会有三种状态:
- pending:等待状态
- fulfill:满足状态,调用resolve时处于该状态并回调.then()
- reject:拒绝状态,调用reject时处于该状态并回调.catch()
其实then的参数里是有两个函数的,第一个是满足状态状态下执行,第二个在拒绝状态下执行,调用resolve的时候就会打印data,调用reject的时候就会打印err
new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('成功')
reject('失败')
}, 1000);
}).then(data=>{
console.log('resolve',data);
},err=>{
console.log('reject',err);
})