1、什么是promise
- 1、promise是异步编程的一种解决方案
- 2、什么时候会处理异步事件呢
主要是网络请求
当封装一个网络请求的函数,由于不能立刻拿到结果(耗时操作),往往会传入另一个函数,在数据请求成功时,将数据通过传入的函数回调出去。
以上只是在简单网络请求的时候可行,如果在复杂请求时,则会出现回调地狱。
回调地狱:回调里面还有回调,多层回调,就称为回调地狱
promise是一个封装的类,用来解决回调地狱的问题,以一种优雅的方式来解决多层回调的问题
2、一个简单的promise
- 1、原始的异步操作
<script>
//1、使用timeout
setTimeout(() => {
console.log('hello world');
}, 1000);
</script>
- 2、new一个promise,把异步操作封装在里面
new Promise的构造函数的参数列表里面需要传一个函数,该函数主要包含两个参数,
resolve:请求得到相应
reject:请求被拒绝
new Promise((resolve,reject)=>{
})
- 3、一个promise实例化实例
<script>
//promise使用了链式的编程,解决完一个再解决下一个
//Promise的参数需要一个函数
new Promise((resolve,reject)=>{//resolve,reject本身也是一个函数
//第一次网络请求
setTimeout(() => {
resolve();//调用resolve函数,并在new出promise实例后调用then函数
}, 1000);
}).then(()=>{
//在then函数里面传入一个回调函数,执行异步操作(耗时操作)
//第一次拿到结果的处理代码
console.log('这是一次网络耗时操作');
//执行完异步操作之后,如果还有进一步的异步操作,可以返回一个新的promise对象
return new Promise((resolve,reject)=>{
//在then函数里面传入一个回调函数,执行异步操作(耗时操作)
//第二次网络请求
setTimeout(() => {
resolve();
}, 1000);
}).then(()=>{
//第二次拿到结果的处理代码
console.log('这是一次网络耗时操作');
//如果还需要执行异步操作再不断地返回新的promise对象
//弹幕里说,相当于一个承诺(promise)当遇到resolve(),即请求成功,则执行then的语句
//下面要执行第三次网络请求,代码略
})
})
</script>
3、什么情况下会用到promise
- 1、一般情况下右异步操作时,使用promise对这个异步操作进行封装
- 2、执行传入的回到函数时,会传入两个参数,
resolve,reject本身又是函数 - 3、promise将网络请求和处理代码分开
- 4、上例,如果请求不成功,执行cath()函数
<script>
new Promise((resolve,reject)=>{
setTimeout(() => {
resolve();
reject();
}, 1000);
}).then(()=>{
console.log('then处理函数');
})
.catch(()=>{
console.log('请求不成功的时候处理函数');
});
</script>
4、Promise的三种状态
异步操作之后会有三种状态
pending:等待状态,如正在进行网络请求,或者定时器还没到点
fulfill:满足状态,当主动回调了resolve时,就处于该状态,并且会回调.then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调catch()
5、Promise的其他处理形式
<script>
new Promise((resolve,reject)=>{
setTimeout(() => {
resolve();
reject();
}, 1000);
}).then(()=>{
console.log('then处理函数');
},err=>{
console.log(err);
})
</script>
6、Promise的链式调用
从流程图上看,无论是then还是catch都是可以返回一个Promise对象,所以我们的代码其实是可以进行链式调用的
可以直接通过Promise包装一下新的数据,将Promise对象放回
-
Promise.resovle():将数据包装成Promise对象,并且在内部回调resovle()函数
-
Promise.reject():将数据包装成Promise对象,并且在内部回调reject()函数
-
1、传统写法
<script>
//网络请求的结果是aaa(先自行处理),然后在进入then等位置对aaa进行处理,
//然后在进入then等位置对aaa进行处理,
//处理aaa之前先自己进行处理,
//再进入下一个then进行处理
new Promise((resolve,reject)=>{
setTimeout(() => {
//获取到一个请求结果
resolve(data);
}, timeout);
}).then(res=>{
//1、自己先处理若干行代码
console.log(res,'第1层的若干行代码');
//2、return一个Promise,对结果进行第一次的处理
return new Promise((resolve,reject)=>{
resolve(res+'执行若干操作')
}).then(res=>{
console.log(res,'第2层的若干行代码');
})
});
</script>
- 2、改进链式写法
<script>
//网络请求的结果是aaa(先自行处理),然后在进入then等位置对aaa进行处理,
//然后在进入then等位置对aaa进行处理,
//处理aaa之前先自己进行处理,
//再进入下一个then进行处理
new Promise((resolve,reject)=>{
setTimeout(() => {
//获取到一个请求结果
resolve(data);
}, timeout);
}).then(res=>{
//1、自己先处理若干行代码
console.log(res,'第1层的若干行代码');
//2、return一个Promise,对结果进行第一次的处理
return Promise.resolve(res+'执行若干操作');
}).then();
</script>
- 3、再次改进链式写法
省略掉 Promise.sovle();
<script>
//网络请求的结果是aaa(先自行处理),然后在进入then等位置对aaa进行处理,
//然后在进入then等位置对aaa进行处理,
//处理aaa之前先自己进行处理,
//再进入下一个then进行处理
new Promise((resolve,reject)=>{
setTimeout(() => {
//获取到一个请求结果
resolve(data);
}, timeout);
}).then(res=>{
//1、自己先处理若干行代码
console.log(res,'第1层的若干行代码');
//2、return一个Promise,对结果进行第一次的处理
//内部会自动进行Promise包装
return res+'执行若干操作';
}).then();
</script>
4、网络请求不成功的情形
<script>
//网络请求的结果是aaa(先自行处理),然后在进入then等位置对aaa进行处理,
//然后在进入then等位置对aaa进行处理,
//处理aaa之前先自己进行处理,
//再进入下一个then进行处理
new Promise((resolve,reject)=>{
setTimeout(() => {
//获取到一个请求结果
resolve(data);
}, timeout);
}).then(res=>{
//1、自己先处理若干行代码
console.log(res,'第1层的若干行代码');
//2、return一个Promise,对结果进行第一次的处理
//内部会自动进行Promise包装
return Promise.reject(res+'这是网络请求不成功的时候的操作')
}).then();
</script>
</body>
不成功的时候也可以不return,可以直接抛出异常
<script>
//网络请求的结果是aaa(先自行处理),然后在进入then等位置对aaa进行处理,
//然后在进入then等位置对aaa进行处理,
//处理aaa之前先自己进行处理,
//再进入下一个then进行处理
new Promise((resolve,reject)=>{
setTimeout(() => {
//获取到一个请求结果
resolve(data);
}, timeout);
}).then(res=>{
//1、自己先处理若干行代码
console.log(res,'第1层的若干行代码');
//2、return一个Promise,对结果进行第一次的处理
//内部会自动进行Promise包装
throw 'erro message'
}).then();
</script>
7、Promise的all方法
当有两个网路请求的时候(需求依赖两个请求才能完成)
all方法里面要求传一个可迭代对象,可以是一个数组,对象
Promise.all(Iterator)
- 1、使用ajax的请求的例子
<script>
Promise.all([
new Promise((resolve,reject)=>{
//ajax的第一个网络请求
$ajax({
url:'',
success:function(data){
resolve(data);
}
})
}),
new Promise((resolve,reject)=>{
//ajax的第2个网络请求
$ajax({
url:'',
success:function(data){
resolve(data);
}
})
})
]).then(resualts=>{
//两个请求同时成功时候进行处理
resualts.log();
})
</script>
- 2、使用settimeout的请求的例子
<script>
Promise.all([
new Promise((resolve,reject)=>{
//settimeout模拟第一个网络请求
setTimeout(() => {
resolve({name:'zhangsan',age:12})
}, 2000);
}),
new Promise((resolve,reject)=>{
//settimeout模拟第一个网络请求
setTimeout(() => {
resolve({name:'lisi',age:22})
}, 1000);
})
]).then(resualts=>{
//两个请求同时成功时候进行处理
console.log(resualts);
})
</script>