ES6 Promise的用法,async/await异步处理同步化

一、为什么要使用Promise

“回调地狱”这个词,不知道大家听过没有,就是异步调用获取到结果后,为下一个异步函数提供参数,所以就会一层一层的出现回调里面嵌入回调,导致层次很深,代码维护起来特别的复杂,看一下下面的小案例大家就知道什么意思了。

<template>
	<view>
		Promise
	</view>
</template>

<script>
	export default {
		data() {
			return {

			};
		},
		onLoad() {
			this.getData()
		},
		methods: {
			getData() {
				//获取分类列表id
				uni.request({
					url: "https://ku.qingnian8.com/dataApi/news/navlist.php",
					success: res => {
						console.log(res)
						let id = res.data[0].id
						// 根据分类id获取该分类下的所有文章
						uni.request({
							url: "https://ku.qingnian8.com/dataApi/news/newslist.php",
							data: {
								cid: id
							},
							success: res2 => {
								//获取到一篇文章的id,根据文章id找到该文章下的评论
								let id = res2.data[0].id;
								console.log(res2)
								uni.request({
									url: "https://ku.qingnian8.com/dataApi/news/comment.php",
									data: {
										aid: id
									},
									success: res3 => {
										//找到该文章下所有的评论
										console.log(res3)
									}
								})
							}
						})
					}
				})
			}
		}
	}
</script>

<style lang="scss">

</style>

大家看到上的代码了没有,数一数有几层嵌套,出现了几个success回调,这个案例的嵌套还算是少的那,还有比这更夸张的,这就是所谓的回调地狱,层层嵌套,要是维护起这样的代码来,直接会把新手劝退的,自己写过的代码要是不加注释也不知道这到底是干嘛的。
在没有ES6的promise时候原来是怎么优化的那,把每一个request请求封装出一个函数将结果进行返回,这就是原来常用的回调函数方案,将上述代码可以改造成如下代码:
调用部分↓

<template>
	<view>
		Promise
	</view>
</template>

<script>
	export default {
		data() {
			return {

			};
		},
		// 在onload初始化后调用相应的函数
		onLoad() {
			//调用导航函数,并拿到函数的返回值
			this.getNav(res => {
				let id = res.data[0].id;
				//拿到分类id作为参数
				this.getArticle(id, res2 => {
					//拿到文章id作为参数
					let id = res2.data[0].id;
					this.getComment(id, res3 => {
						//最终获取到第一个分类下,第一篇文章下,所有评论
						console.log(res3)
					})
				})
			});
		},
		methods: {
			//先获取导航分类接口,将结果进行返回,到调用函数的地方获取
			getNav(callback) {
				uni.request({
					url: "https://ku.qingnian8.com/dataApi/news/navlist.php",
					success: res => {
						callback(res)
					}
				})
			},

			//获取文章数据,将文章列表进行返回
			getArticle(id, callback) {
				uni.request({
					url: "https://ku.qingnian8.com/dataApi/news/newslist.php",
					data: {
						cid: id
					},
					success: res => {
						callback(res)
					}
				})
			},

			//获取文章下的所有评论
			getComment(id, callback) {
				uni.request({
					url: "https://ku.qingnian8.com/dataApi/news/comment.php",
					data: {
						aid: id
					},
					success: res => {
						callback(res)
					}
				})
			}
		}
	}
</script>

<style lang="scss">

</style>

看上面大家可能都看懵了,仔细看来,并没有解决回调地狱的问题,还是回调里面嵌套回调,只是把函数独立出来了,看着清晰条理了一些而已,但是维护难度还是有的,说以随着ES6的普及,这种方案逐渐边缘化,取而代之的就是promise方案了。

二、什么是promise

promise是解决异步的方法,本质上是一个构造函数,可以用它实例化一个对象。对象身上有resolve、reject、all,原型上有then、catch方法。promise对象有三种状态:pending(初识状态/进行中)、resolved或fulfilled(成功)、rejected(失败)

  1. pending。它的意思是 “待定的,将发生的”,相当于是一个初始状态。创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态。
  2. resolved。表示解决了,就是说这个承诺实现了。 要实现从pending到resolved的转变,需要在 创建Promise对象时,在函数体中调用了resolve方法
  3. rejected。拒绝,失败。表示这个承诺没有做到,失败了。要实现从pending到rejected的转换,只需要在创建Promise对象时,调用reject函数。
    看上面的引用,promise就是用来解决异步的方法,光看上面的解释可能不懂什么意思,但是它后面说的实例化对象后端方法,你肯定用过,如then、catch等,通过以下代码打印一下他里面的方法。

三、将回调函数修改为promise方案

<template>
	<view>
		Promise
	</view>
</template>

<script>
	export default {
		data() {
			return {

			};
		},
		// 在onload初始化后调用相应的函数
		onLoad() {
			//promise链式调用
			this.getNav().then(res => {
				let id = res.data[0].id;
				return this.getArticle(id);
			}).then(res => {
				let id = res.data[0].id;
				return this.getComment(id)
			}).then(res => {
				console.log(res)
			})
		},
		methods: {
			//先获取导航分类接口,将结果进行返回,到调用函数的地方获取
			getNav(callback) {
				return new Promise((resolve, reject) => {
					uni.request({
						url: "https://ku.qingnian8.com/dataApi/news/navlist.php",
						success: res => {
							resolve(res)
						},
						fail: err => {
							reject(err)
						}
					})
				})
			},


			//获取文章数据,将文章列表进行返回
			getArticle(id) {
				return new Promise((resolve, reject) => {
					uni.request({
						url: "https://ku.qingnian8.com/dataApi/news/newslist.php",
						data: {
							cid: id
						},
						success: res => {
							resolve(res)
						},
						fail: err => {
							reject(err)
						}
					})
				})
			},

			//获取文章下的所有评论
			getComment(id) {
				return new Promise((resolve, reject) => {
					uni.request({
						url: "https://ku.qingnian8.com/dataApi/news/comment.php",
						data: {
							aid: id
						},
						success: res => {
							resolve(res)
						},
						fail: err => {
							reject(err)
						}
					})
				})
			}
		}
	}
</script>

<style lang="scss">

</style>

经过一番改造,代码的可读性是不是更好了那,虽然多了几行代码,但是在调用的时候实在是太优雅了,清晰明了。

如果你觉得,这种调用方式还是有嵌套不够清晰,还有大杀器,就是目前最为流行的await/async了,这是ES7新引入的概念。

四、await / async ES7的新规范,异步处理同步化

这两个命令是成对出现的,如果使用await没有在函数中使用async命令,那就会报错,如果直接使用async没有使用await不会报错,只是返回的函数是个promise,可以,但是没有意义,所以这两个一起使用才会发挥出它们本身重要的作用。
这两个命令怎么用那,还是通过上面的案例,来该着一下then的链式调用代码。

async onLoad() {
  let id,res;
  res=await this.getNav();
  id=res.data[0].id;
  res=await this.getArticle(id);
  id=res.data[0].id;
  res=await this.getComment(id);
  console.log(res)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值