- 异步请求的痛点已经回调地狱是如何产生的
- 使用callback回调函数的方式封装返回值
- promise的三种状态以及then的链式调用法改造
- Promise.all封装多个对象统一处理方案
- async await异步处理同步化对代码进行重构
本篇文章适用于有一定Promise
基础的同学
很多同学,对
promise
比较陌生,只是知道怎么用,无非就是.then().catch()
,至于为什么这样用很多同学比较迷茫,网上很多介绍的都太理论化、抽象化,希望能通过这篇文章帮你深入了解一下promise
的前因后果。
一、异步请求的痛点
下面的举例就以
uniapp
里面的网络请求uni.request()
为例了,如果你做的是微信小程序wx.request()
也是一样的,还有jQuery的ajax()
,这些都是异步请求,通过success
回调函数获取数据的,那有童鞋会问为什么不用vue
的axios
,因为axios
网络请求已经封装promise
了。
onLoad() {
this.getData()
},
methods: {
getData() {
// 获取分类列表
uni.request({
url: "https://ku.qingnian8.com/dataApi/news/navlist.php",
success: (res) => {
// 获取到一个分类的id,查询该分类下面的所有文章
const id = res.data[0].id
uni.request({
url: "https://ku.qingnian8.com/dataApi/news/newslist.php",
data: {
cid: id
},
success: (res2) => {
// 获取到一篇文章的id,根据文章id找到该文章下的评论
const id = res2.data[0].id
uni.request({
url: "https://ku.qingnian8.com/dataApi/news/comment.php",
data: {
aid: id
},
success: (res3) => {
// 该文章下面的所有评论
console.log(res3);
}
})
}
})
}
})
}
}
二、使用callback回调函数的方式封装返回值
onLoad() {
this.getNavList((res) => {
// 获取到一个分类的id,查询该分类下面的所有文章
const id = res.data[0].id
this.getNewsList(id, (res2) => {
// 获取到一篇文章的id,根据文章id找到该文章下的评论
const id = res2.data[0].id
this.getCommentList(id, (res3) => {
console.log(res3);
})
})
})
},
methods: {
// 第一个异步步请求---获取分类列表
getNavList(callback) {
uni.request({
url: 'https://ku.qingnian8.com/dataApi/news/navlist.php',
success: (res) => {
callback(res)
}
})
},
// 第二个异步步请求---根据分类id查询该分类下面的所有文章
getNewsList(id, callback) {
uni.request({
url: 'https://ku.qingnian8.com/dataApi/news/newslist.php',
data: {
cid: id
},
success: (res) => {
callback(res)
}
})
},
// 第三个异步步请求---根据文章id查询该文章下面的所有评论
getCommentList(id, callback) {
uni.request({
url: "https://ku.qingnian8.com/dataApi/news/comment.php",
data: {
aid: id
},
success: (res3) => {
// 找到该文章下面的所有评论
callback(res3);
}
})
},
}
三、promise的三种状态以及then的链式调用
promise
是解决异步的方法,本质上是一个构造函数,可以用它实例化一个对象。对象身上有resolve、reject、all
,原型上有then、catch
方法。promise
对象有三种状态:pending
-(初识状态/进行中) 、resolved
或fulfilled
(成功) 、rejected
(失败)
- pending。它的意思是"待定的,将发生的”,相当于是一个初始状态。创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态。
- resolved。表示解决了,就是说这个承诺实现了。 要实现从pending到resolved的转变,需要在 创建Promise对象时,在函数体中调用了resolve方法
- rejected。拒绝,失败。表示这个承诺没有做到,失败了。要实现从pending到rejected的转换,只需要在创建Promise对象时,调用reject函数。
onLoad() {
// 3. 使用Promise封装
this.getNavList().then((res) => {
// 获取到一个分类的id,查询该分类下面的所有文章
const id = res.data[0].id
return this.getNewsList(id)
}).then((res2) => {
// 获取到一篇文章的id,根据文章id找到该文章下的评论
const id = res2.data[0].id
return this.getNewsList(id)
}).then((res3) => {
console.log(res3);
}).catch((error) => {
// 以上三个异步请求的错误都会在最后一个catch函数里面去捕获
console.log(error);
})
},
methods: {
// 第一个Promise异步步请求封装---获取分类列表
getNavList() {
return new Promise((resolve, reject) => {
uni.request({
url: 'https://ku.qingnian8.com/dataApi/news/navlist.php',
success: (res) => {
resolve(res)
},
fail: (error) => {
reject(error)
},
})
})
},
// 第二个Promise异步步请求---根据分类id查询该分类下面的所有文章
getNewsList(id) {
return new Promise((resolve, reject) => {
uni.request({
url: 'https://ku.qingnian8.com/dataApi/news/newslist.php',
success: (res) => {
resolve(res)
},
fail: (error) => {
reject(error)
},
})
})
},
// 第三个Promise异步步请求---根据文章id查询该文章下面的所有评论
getCommentList(id) {
return new Promise((resolve, reject) => {
uni.request({
url: 'https://ku.qingnian8.com/dataApi/news/comment.php',
success: (res) => {
resolve(res)
},
fail: (error) => {
reject(error)
},
})
})
},
}
四、Promise.all封装多个对象统一处理方案(常处理没有依赖关系的异步请求)
uni.showLoading({
title: '数据加载中'
})
const p1 = this.getNavList()
const p2 = this.getNewsList()
const p3 = this.getCommentList()
Promise.all([p1, p2, p3]).then((resAll) => {
const [res, res2, res3] = resAll
console.log(res, res2, res3);
uni.hideLoading()
}).catch((error) => {
// 只要有一个请求失败了,都会被捕获,返回的是第一个报错的信息
})
五、async await 异步处理同步化对代码进行重构
// 5. async_await异步处理同步化对代码进行重构
let res, id
res = await this.getNavList()
id = res.data[0].id
res = await this.getNewsList(id)
id = res.data[0].id
res = await this.getCommentList(id)
console.log(res);
网友评论