目录
传统的回调函数封装
ES6中的promise
异步同步化(终极)
传统的回调函数封装
js中的回调函数的理解:回调函数就是传递一个参数化函数,就是将这个函数作为一个参数传到另外一个主函数里面,当那个主函数执行完之后,再执行传递过去的函数,走这个过程的参数化的函数,就叫回调函数,换个说法也就是被作为参数传递到另一个函数(主函数)的那个函数就叫做回调函数。
传统的js回调函数我们可以用callback的方式来实现
举例:
我们用vue2的写法先获取到http://ku.qingnian8.com/dataApi/news/navlist.php
注意:这个后端接口时哔哩哔哩咸虾米老师的后端接口,我们只用来学习使用,若有非法使用,必追究责任!
这个后端的接口的数据,然后我们通过callback这个方法来将我们获取到的res中的数据回调出去,
注意:getNav()这个函数获取到的是后端接口中的最外层的数据:
代码语言:javascript复制 methods: {
getNav(callback){
uni.request({
url:"http://ku.qingnian8.com/dataApi/news/navlist.php",
success:res=>{
callback(res)
}
})
},
getList(id){
uni.request({
url:"http://ku.qingnian8.com/dataApi/news/newslist.php",
data:{
cid:id
},
success:res=>{
console.log(res)
}
})
}
}
注意:因为getList这个方法我们时用来获取接口中第二层的数据,他是根据最外层数据的id来定位分类的,所以我们这里需要传递一个id作为形参!
代码语言:javascript复制 onLoad() {
this.getNav(res=>{
let id = res.data;
console.log(id)
this.getList(id,res=>{
let id=res.data[0].id;
})
})
// })
},
然后我们在onLoad()这个函数生命周期函数中给getNav和getList两个我们自定义的函数做的回调值,我们接收它,然后并分别将他们对应的value数据值打印出来!
http://ku.qingnian8.com/dataApi/news/navlist.php这个Api接口是用的哔哩哔哩的咸虾米老师的接口!
我们可以通过这样一种传统的回调函数callback方式来将我们自定义获取后端接口的api的方法进行封装!
ES6中的promise
Promise特点
仅只有3种状态:进行中,已成功,已失败,且只有异步结果可以影响状态,其它都不能影响。
优点:避免了层层嵌套的回调函数
缺点:无法取消,一旦新建它就会立即执行,无法中途取消。当处于pending状态时,无法得知目前进展到哪一个阶段(是刚刚开始还是即将完成)。
第一种 catch 方法可以捕获到 catch 之前整条 promise 链路上所有抛出的异常。
第二种 then 方法的第二个参数捕获的异常依赖于上一个 Promise 对象的执行结果。
promise.then(successCb, faildCd) 接收两个函数作为参数,来处理上一个promise 对象的结果。then f 方法返回的是 promise 对象。第一种链式写法,使用catch,相当于给前面一个then方法返回的promise 注册回调,可以捕获到前面then没有被处理的异常。第二种是回调函数写法,仅为为上一个promise 注册异常回调。
如果是promise内部报错 reject 抛出错误后,then 的第二个参数就能捕获得到,如果then的第二个参数不存在,则catch方法会捕获到。
如果是then的第一个参数函数 resolve 中抛出了异常,即成功回调函数出现异常后,then的第二个参数reject 捕获捕获不到,catch方法可以捕获到。
我们同样还是以这个后端接口为例http://ku.qingnian8.com/dataApi/news/navlist.php
将callback方法替换为Promise这个方法,当然Promise方法有两个值,一个是resolve(请求成功后打印出的数据)、reject(请求失败后打印的提示内容)
然后我们写完此方法时,我们还需要把它return出去,最终能让我们onLoad这个生命周期函数接收到它的值!
代码语言:javascript复制 methods: {
getNav(){
return new Promise((resolve,reject)=>{
uni.request({
url:"http://ku.qingnian8.com/dataApi/news/navlist.php",
success:res=>{
resolve(res)
},
fail:err=>{
reject(err)
}
})
})
},
getList(id){
return new Promise((resolve,reject)=>{
uni.request({
url:"http://ku.qingnian8.com/dataApi/news/newslist.php",
data:{
cid:id
},
success:res=>{
resolve(res)
},
fail:err=>{
reject(err)
}
})
})
}
}
在onLoad这个生命周期函数中,我们需要将后去到的值进行一下打印
return this.getList(id)这句代码的意思是获取到上面res.data[0].id这个最外层的数据的id,并把最外层对应的里面的第二层的数据return返回出去,然后再.then,这个.then是对于return this.getList(id)这行代码来说的,是将后端接口的第二层数据打印出来!
代码语言:javascript复制onLoad() {
this.getNav().then(res=>{
console.log(res)
let id = res.data[0].id;
return this.getList(id)
}).then(res=>{
console.log(res)
})
}
显示效果
异步同步化(初级):
优点:可以有效的避免页面请求数据的过程中不断的一步一步的请求导致的页面卡顿问题!
使用Promise.all的方式,等待这两个网络请求都请求完成之后,将所有获取的数据存放在这个数组当中一块打印!
代码语言:javascript复制 onLoad() {
let p1=this.getNav();
let p2=this.getList(51);
Promise.all([p1,p2]).then(res=>{
uni.hideLoading()
console.log(res)
})
}
异步同步化(终极)
async 函数
async函数就是 Generator 函数的语法糖。对比Generator的改进主要体现在:
- 内置执行器: 不需要co模块, 也不需要手动调用next(),和普通函数一样调用就好了.
- 更好的语义:比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
- 更广的适用性:await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
- 返回值是 Promise:返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
当代码遇到await时下一行代码会等待慈航代码请求完成再开始运行!
代码语言:javascript复制async onLoad() {
let res = await this.getNav();
console.log(res)
let id = res.data[0].id;
let res1 = await this.getList(id);
console.log(res1)
}
代码语言:javascript复制 methods: {
getNav(){
return new Promise((resolve,reject)=>{
uni.request({
url:"http://ku.qingnian8.com/dataApi/news/navlist.php",
success:res=>{
resolve(res)
},
fail:err=>{
reject(err)
}
})
})
},
getList(id){
return new Promise((resolve,reject)=>{
uni.request({
url:"http://ku.qingnian8.com/dataApi/news/newslist.php",
data:{
cid:id
},
success:res=>{
resolve(res)
},
fail:err=>{
reject(err)
}
})
})
}
}