网络请求的回调地狱
我们来考虑下面的场景(有夸张的成分):
我们需要通过一个url1从服务器加载一个数据data1,data1中包含了下一个请求的url2
我们需要通过data1取出url2,从服务器加载数据data2,data2中包含了下一个请求的url3
我们需要通过data2取出url3,从服务器加载数据data3,data3中包含了下一个请求的url4
发送网络请求url4,获取最终的数据data4
上面的代码有什么问题吗?
正常情况下,不会有什么问题,可以正常运行并且获取我们想要的结果。
但是,这样代码难看而且不容易维护。
我们更加期望的是一种更加优雅的方式来进行这种异步操作。
如何做呢?就是使用Promise。
Promise可以以一种非常优雅的方式来解决这个问题。
promise的基本使用
使用setTimeOut模拟网络请求
//第一次网络请求
setTimeout(()=>{
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
//第二次网络请求
setTimeout(()=>{
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
},1000)
//第三次网络请求
setTimeout(()=>{
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
},1000)
},1000)
这样的代码难看,可以使用Promise
new Promise((resolve, reject)=>{
//第一次网路请求
setTimeout(()=>{
resolve();
},1000)
}).then(data => {
//第一次拿到结果的处理代码
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
return new Promise((resolve, reject)=>{
//第二次网路请求
setTimeout(()=>{
resolve();
},1000)
},1000)
}).then(data => {
//第二次拿到结果的处理代码
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
return new Promise((resolve, reject)=>{
//第三次网路请求
setTimeout(()=>{
resolve();
},1000)
},1000)
}).then(data => {
//第三次拿到结果的处理代码
console.log('hello world');
console.log('hello world');
console.log('hello world');
console.log('hello world');
})
使用promise链式调用,代码更加清晰
Promise三种状态
首先, 当我们开发中有异步操作时, 就可以给异步操作包装一个Promise
异步操作之后会有三种状态
我们一起来看一下这三种状态:
pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
链式调用简写
new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('aaa');
},1000)
}).then(data => {
console.log(data,'第一层的10行处理代码');
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(data + '111');
},1000)
},1000)
}).then(data => {
console.log(data,'第二层的10行处理代码');
})
return new Promise((resolve, reject)=>可以简写为 promise.resolve,promise.reject
简写为:
new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('aaa');
},1000)
}).then(data => {
console.log(data,'第一层的10行处理代码');
return Promise.resolve(data + '111');
}).then(data => {
console.log(data,'第二层的10行处理代码');
})
还可以再次简写:return Promise.resovle(data)简写为return data
new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('aaa');
},1000)
}).then(data => {
console.log(data,'第一层的10行处理代码');
return data + '111';
}).then(data => {
console.log(data,'第二层的10行处理代码');
})
all的用法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调
Promise.all([
//操作1
new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('result1');
},1000)
}),
//操作2
new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('result2');
},1000)
}),
]).then(results =>{
console.log(results);
})
操作1、操作2执行完才会调用then
参考:
https://www.jiagou1216.com/life/front/801.html
https://www.cnblogs.com/lvdabao/p/jquery-deferred.html