手机版

ES6的异步终极解决方案共享

时间:2021-08-21 来源:互联网 编辑:宝哥软件园 浏览:

前言

Promise异步生成器是在ES6之后提出的,它们可以用来解决之前JS异步调用带来的一系列问题,比如著名的回调地狱!

什么是回调地狱?

在前面的js中,我们无法知道异步操作是否完成。为了在异步操作完成后执行特定的代码,我们需要传入一个回调函数。请看下面的栗子:

这是请求完成后执行特定代码的一个简单示例(可以理解为异步操作)

//我们需要在请求完成后输出请求完成。请看回调函数show(params) {request('这是request参数',()={ console . log(' request completed ')})}/* * *模拟发起http请求的参数* @param {object}数据请求* @param {function}回调函数*/function请求(data,CallBack) {//下面的计时器模拟请求时间setTimeout(data={ callBack(data);}, 3000);} show()回调当然很简单。如果您需要在该请求完成后立即启动下一个请求,该怎么办?例如,您需要请求10次,并且您必须在最后一次请求完成后发出下一次请求,以查看回调地狱是什么样子的

//我们需要在请求完成后输出请求完成。请参考回调方法函数show(params) {request('这是请求参数',()={console.log('请求完成一次')request('这是请求参数',()={console.log('请求完成两次')request('这是请求参数',()={console.log('请求完成三次')request('这是请求参数',()={console.log('请求完成四次')request('这是请求参数',()={console.log('请求完成5次'))//这是.})})})})})})}/* * *模拟发起http请求的参数* @param {object}数据请求* @param {function}回调函数*/下面的计时器模拟请求时间setTimeout(data={ callBack(data);},1000);} show()这是第五次回调,但是代码的可读性极差!

让我们先来看看Promise异步生成器是如何解决这个问题的,然后再来谈谈它以后是如何使用的

首先,承诺

//我们需要在请求完成后输出请求完成。请参考回调函数show(params) {request('这是请求参数')。然后(resolve={console.log('请求完成一次');返回请求(“这是请求参数”)})。然后(resolve={console.log('请求完成两次');返回请求(“这是请求参数”)})。然后(resolve={console.log('请求已完成3次');返回请求(“这是请求参数”)})。然后(resolve={console.log('请求已完成4次');返回请求(“这是请求参数”)})。然后(resolve={console.log('请求完成5次');Return request('这是request参数')})}/* * *模拟发起http请求的参数* @param {object}数据请求* @ param { function } callBack function */function request(数据){ return new Promise(resolve)={//下面的计时器模拟请求时间settimeout(数据={resolve(数据)},1000);})} show()仍然很长,但至少它的嵌套很少,可读性比以前更好

让我们看看异步

请记住,异步必须与Promise一起使用

//我们需要在请求完成后输出请求完成。请参考回调方法async函数show(params){ let result=wait request('这是请求参数')console.log('请求完成一次');Result=await request('这是请求参数')console.log('请求完成两次');Result=await request('这是请求参数')console.log('请求完成3次');Result=await request('这是请求参数')console.log('请求已完成4次');Result=await request('这是请求参数')console.log('请求完成5次');}/* * *模拟发起http请求的参数* @param {object}数据请求* @param {function}回调函数*/function request(数据){return new promise (resolve={//以下计时器模拟请求时间settimeout(数据={resolve(数据)},1000);})} show()代码是否更短?看起来和同步一样。实际上,这是以同步的方式编写异步代码,并且该代码也是同步执行的

最后,看看发电机

//我们需要在请求完成后输出请求。请参考回调方法函数* show(){ let a1=yield request(' request parameter ',()={console.log('这是第一次调用');});让a2=yield request(' request parameter ',)={console.log('这是第二次调用');});让a3=yield request(' request parameter ',)={console.log('这是第三次调用');});让a4=yield request(' request parameter '),()={console.log('这是第四次调用');});让a5=yield request(' request parameter '),()={console.log('这是第五次调用');});}/* * *模拟http请求的发起* @param {object}数据请求参数* @param {function}回调函数*/functionrequest(数据,回调){//下面的计时器模拟请求时间settimeout (()={callback(数据)},1000);}让a=show()a . next();a . next();a . next();a . next();a . next();以上就是异步编程的ES6解决方案。接下来,让我们仔细看看这三种方法

一、保证

关于Promise的一些原型和功能,请访问官方链接

Promise的中文名字,意思是承诺,保证,

你可以把Promise理解为JS的一个Promise,也就是对异步操作的一个Promise。不管异步操作能否成功执行,JS已经承诺用promise处理所有的异步操作,所以我们可以通过promise的状态知道异步操作的执行结果。

承诺有以下状态:

Pending:初始状态既不成功也不失败。Fulfilled:表示操作已完成,状态为成功。被拒绝:表示操作失败。处于挂起状态的Promise对象可能会更改为已履行状态,并将值传递给相应的状态处理方法,或者它可能会更改为已拒绝状态,并传递失败消息。当这些情况发生时,将调用由Promise对象的then方法绑定的处理程序

上述Promise原型中的函数可以接收2个参数(解析[,拒绝])

第一个参数解析是成功的处理,它的类型是函数。异步成功后,您可以执行一些操作

第二个参数reject是对失败的处理,它的类型是Function。异步失败后,您可以执行一些操作

在正常情况下,那么我们只传递一个参数,也就是默认的成功处理,而失败处理将使用catch函数

catch函数只有一个参数,这意味着拒绝失败

让我们看一下then catch的用例

函数show(params) {//normal request成功操作request('这是request参数')。然后(resolve={ console . log(resolve));})//在then request中执行成功和失败的操作(“这是request参数”)。然后(resolve={//这是成功控制台. log(resolve);},reject={//这里是失败控制台. log(reject);})//正常请求失败操作请求('这是一个请求参数')。catch (reject={console.log(拒绝));})}/* * *模拟发起http请求的参数* @param {object}数据请求* @param {function}回调函数*/function request(数据){return new promise ((resolve,Reject)={//下面的计时器模拟请求时间setTimeout(数据={//resolve(' request succeed ')Reject(' request failed ')},1000);})} show()可以让你的异步操作更加优雅易读。同时,Promise在ES6插件中应用广泛,所以掌握Promise很有必要

二.异步/等待

更多详情,请查阅官方文件

Async关键字用于定义一个函数,该函数用于标识该函数是异步函数

记住,记住,记住,await关键字只在异步函数中有效。如果在异步函数函数之外使用wait,将只会得到一个语法错误语法错误

async关键字放在函数声明之前,例如:

async function test(){ } async()={ } async data={ } class test { async show(){ } }无论是普通函数、Lambda表达式还是ES6的类,这个关键字都会放在函数声明之前

当调用声明异步的函数时,将返回一个Promise对象

Await关键字放在异步操作的调用之前。wait将导致异步函数在执行异步操作时暂停代码执行,直到异步操作返回的Promise状态变为已履行或已拒绝。此时,代码将继续执行并自动解析Promise返回的值。无论成功还是失败,都会解析接收到的在await关键字前面定义的参数。请参见示例3360。

Class Test {/** *线程睡眠* @param {number}定时器睡眠毫秒数*/sleep(timer){返回新的承诺(resolve={ settimeout(()={ resolve(timer)},timer);})} }让T=new Test();Async函数show () {console.log('第一次');等待睡眠(1000)控制台日志(“第二次”);}show()上面的例子调用了show函数,它会立即打印第一次,延迟1000毫秒后会打印第二次

原理是模仿Java的线程Sleep函数睡眠

第一次打印后,会调用T的Sleep函数,Sleep函数返回一个Promise。定时器执行后,调用Promise的解析函数会将Promise的状态变为已履行。此时,await检测到Promise状态的变化,继续执行代码,并输出第二次。

三.发电机

生成器是ES6标准引入的一种新的数据类型,通过在函数名前加*来使用。生成器类似于普通函数,但可以多次返回。

所有函数都有默认返回值。如果没有明确定义,就会返回undefined,生成器也不例外!

生成器使用yield关键字返回一半的值。请查看案例

函数* a(num){ let sum=yield num 1 console . log(sum);//2这里是next传入的值(r.value)让sum2=yield sum2}让result=a(1);让r=result . next()console . log(r);//这里返回第一个yield的值2 console . log(result . next(2));//这里,返回第二个yield 4 console.log的值(result . next());//这里没有第三收益率

第一个输出是第一个收益率的值。此时,num是调用a函数时传入的值1,yield返回num 1,因此第一行中打印的对象的值是2

第二次打印是sum值,它是在第一个yield关键字之前收到的值。这个值由下面的result.next(2)传入,next函数传入的参数将赋给相应yield关键字左侧接收的变量,该变量是大写的sum变量。

第三个输出是A函数中第二个收益率返回的值。此时,sum是next(2)第一次传入的2,所以这次返回的值是2 ^ 2,所以值是4。

第四个输出是最后一个next(),但是上层生成器没有返回相应的yield,因此此时的值是未定义的

yield返回的值是一个具有两个属性的对象:done和值。

完成指示生成器是否已完成执行。当不返回yield时,done的值为true,这意味着当前生成器已经完成执行。value指示yield关键字右侧的表达式返回的值。当没有产量时,该值为undefinedgenerator,支持迭代器操作。例3360。

函数* a(num){ let sum=yield num 1 console . log(sum);//2这里是next传入的值(r.value)让sum2=yield sum2}让result=a(1);for(结果的常量键){ console.log(键);}

事实证明,生成器实现了迭代器的接口!

嗯,我还没有遇到生成器的实际应用场景,但是听说async/await是生成器的语法糖。

摘要

以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。谢谢你的支持。

版权声明:ES6的异步终极解决方案共享是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。