Promise
# 回调地狱
了解回调地狱之前,先了解下回调函数
和同步任务
和异步任务
区别
# 回调函数
当一个函数作为参数传入另一个函数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为
回调函数
。
// callback()就是回调函数
function getlist(id,callback){
if(id > 10){
callback(id)
}
}
getlist(9,res=>{
console.log(res);
})
2
3
4
5
6
7
8
9
# 同步任务
同步任务在主线程上排队执行,只有前一个任务执行完毕,才能执行下一个任务,JavaScript代码实际上是单线程的程序,那就决定了我们的代码是一行一行的顺序执行的,处理一些简短、快速的运算操作时主线程就够了,如果在同步程序中发送了网络请求,如果超时了,下面的代码依赖于网络请求,那么整个网页将会失去响应。
# 异步任务
异步任务不进入主线程,而是进入异步队列,前一个任务是否执行完毕不影响下一个任务的执行。一个异步过程的执行将不再与原有的序列有顺序关系,特别是对发送网络请求,不确保响应时间时候,异步是最优选择,网络请求无论多长时间,程序将不会在此等待,直接走下面的代码,等异步的请求有了响应,主线程几乎不用关心异步任务的状态了,自己完成回调后续的操作,程序间互不影响。
# 回调地狱
简单来说就是 回调函数里面嵌套回调函数,是实现代码
顺序执行
的一种操作方式,用于解决异步执行
- 缺点
- 代码可读性差,不利于维护
- 代码的扩展性差
- 多个回调之间难以建立联系
- 无法正常使用return 和throw
- 无法正常检索堆栈信息
# 解决回调地狱
# 回调函数
function getComment(id,callback){
uni.request({
url:"xxx",
data:{aid:id},
success(res) {
callback(res);
}
})
},
getComment(10,res=>{})
2
3
4
5
6
7
8
9
10
如果需要多个方法,依然出现多个嵌套,可读性差
# Promise
Promise
是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6
将其写进了语言标准,统一了用法,原生提供了Promise对象。
Promise有3种状态
- pending[待定] 初始状态
- resloved[实现] 操作成功
- rejected[被否决] 操作失败
用法
- 构造函数有两个参数:resloved和rejected,都是回调函数
- resloved函数:异步操作成功后调用,并将异步操作的结果传递出去
- rejected函数:异步操作失败后调用,将失败的信息传递出去
- .then():接收resloved函数传递过来的信息
- .catch():接收rejected函数传递过来的信息
Promise 状态发生改变,就会触发.then()里的响应函数处理后续步骤
Promise 状态一经改变,不会再变
Promise 实例一经创建,执行器立即执行
getComment(){
return new Promise((resolve,reject)=>{})
}
getComment()
.then(res=>{})
.catch(err=>{})
// 处理异步同步化
Promise.all([p1,p2,p3]).then(res=>{console.log(res)})
2
3
4
5
6
7
8
9
# await / async
await / async 是ES7的新规范,异步处理同步化
# 为什么有async/await
Promise虽然跳出了异步嵌套的怪圈,用链式表达更加清晰,但是我们也发现如果有大量的异步请求的时候,流程复杂的情况下,会发现充满了屏幕的then,看起来非常吃力,而ES7的async/await的出现就是为了解决这种复杂的情况
# async/await基本规则
- await关键字只能在使用async定义的函数中使用
- await后面可以直接跟一个Promise实例对象(可以跟任何表达式,更多的是跟一个返回Promise对象的表达式)
- await函数不能单独使用
- await可以直接拿到Promise中resolve中的数据
# promise和async/await区别
promise
是ES6,async/await
是ES7- async/await相对于promise来讲,写法更加优雅
- reject状态:
- promise错误可以通过catch来捕捉,建议尾部捕获错误
- async/await既可以用.then又可以用try-catch捕捉