js异步操作同步化

300 阅读2分钟

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

在javascript中,比如我们在请求数据的时候,举个例子,查询所有的文章列表, 接着拿到文章列表再去查询文章详情.这是两个请求,但是查询文章详情必然要拿到该文章的id,也就是查询文章详情的接口,需要在查询文章列表后来执行,否则就会拿不到文章的id.那如何保证先查询文章列表,再查文章详情呢????

这就是异步操作的同步化, 以下是解决方案:

若查询文章列表的函数是findAll()

查询文章详情的函数是findById()

1. 回调函数嵌套

   
       findAll().then((res)=>{
            
            findById()
 
        })

这种方式如果是简单的业务逻辑可以这样使用,但是若是逻辑复杂就需要多层回调,也就是所谓的回调噩梦,所以不是特别可取

 2.Promise...then方式          

promise的流程如下图所示:

image.png

Promise一旦新建就立刻执行, 此时的状态是Pending(进行中),它接受两个参数分别是resolve和reject.它们是两个函数.

resolve函数的作用是将Promise对象的状态从'未完成'变为'成功'(由Pending变为Resolved), 在异步操作成功时,将操作结果作为参数传递出去;

reject函数的作用是将Promise对象的状态从'未完成'变为失败(由Pending变为Rejected),在异步操作失败时调用,并将异步操作的错误作为参数传递出去.

<script type="text/javascript">
		function foo(){
			    return new Promise((reslove,reject)=>{
			    	findAll().then(()=>{
			    		 reslove();
			    		}).catch(()=>{
			    			reject();
			    		})
			    })
			}
		foo.then((reslove)=>{
			findById()
		})
	</script>

3.generator函数  /  async函数

一.Generator函数

1. 定义

Generator函数是ES6提供的一种异步编程解决方案 , 语法上可以把Generator函数理解为一个状态机,封装了多个内部状态

2.语法

a. function关键字和函数名之间有个*

b.函数体内部使用yield表达式,定义不同的内部状态

例如:

image.png yield只能在Generator函数中使用, 默认情况下,yiled的返回值是undefined

 3.调用

  let a = hello()   此处a为一个迭代器

a.next(  )   每次调用next方法,可以依次获取每个yield的值

 eg. 遍历迭代器的方法

<script type="text/javascript">
		function* foo(){
        	yield 'one';
        	yield 'two';
        	yield 'three';
        	return 'end';
		}
 
		var result = foo()
 
		// 通过while遍历
		let item
		// result.next()返回值为一个对象,即{value:'xxx',done:false/true}
		// 若done的值为false说明还有yield未执行,若为true则表明已执行完
		while(!(item = result.next()).done){
			console.log(item.value)
		}
 
 
		// 通过for of方法
		for(let i of result){
			console.log(r)
		}
 
 
	</script>
 4.请求案例
function* foo(){
	        let c_url='接口地址'
	        // 因为yield执行后返回值为undefined,所以此处需要使用call来拿到请求方法返回值
	        let a = yield call(执行函数,c_url)
 
		}
        /*
					异步函数的执行器{
						1)在上一个请求结束后再去调用下一个请求;
						2)将当前请求结果左右yield表达式的返回值返回
					}
				*/
 
		function call(handler,params){
			handler(params).then((response)=>{
				iterator.next(response)
			})
		}
 
		let iterator = foo()

二. async函数

   1.定义

  async函数是generator函数的语法糖,在generator函数的基础上添加了一些更加方便用户操作的新特性

     2.使用

   例如:

<script type="text/javascript">
		async function foo(){
			// handler为请求方法
			let a = await handler('接口地址')
			return a
		}
 
		// async函数的调用与普通函数一致
		let f = foo() //promise
		f.then((result)=>{
			console.log(result)   //result为foo方法的返回值
		})
	
	</script>

以上就是全部内容啦~