关于java后端程序员接触C#而不得已理解async和await这件事

写在前面:

本人前端小白,刚刚接触前端的异步概念,若有写的不对的地方,评论区直接开喷即可。

众所周知,作为一个Java(jdk1.8)出身的辣鸡后端程序员,jdk1.8代码中本来是没有async和await这件事的,我一度认为它们是前端专有的关键字。排除掉线程,java代码基本是顺序执行的,这种日子直到我遇到了最新版的C#,一切都结束了......

新版C#中,支持开发人员将一个函数声明为异步的。么的办法,回来理解一下前端的async和await,以es6为例

async // asynchronous(译:异步)的简写
await // async wait 的简写

async通常和await配套使用,async用于声明一个函数是异步的,await放在被声明为async的函数内部,用于等待await后面的结果,同时block住整个async的函数(此处暂不考虑awiat的对象是不是promise对象,先情景理解,后面再讲)。async和await的用法如下(ref:ES6之async和await - 简书 (jianshu.com)):

function doubleAfter2seconds(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2 * num)
        }, 2000);
    })
}

async function testResult () {
    console.log('内部调用前')
    let result = await doubleAfter2seconds(30);
    console.log(result);
    console.log('内部调用后')
}

console.log('外部调用前')
testResult();
console.log('外部调用后')

第一个函数function doubleAfter2seconds(num)是一个正常的顺序执行函数,该函数仅返回一个promise对象,先不纠结什么是promise对象,就理解为返回一个对象就行,这个对象会计算 2 * 参数num 的结果,并且等待2000ms后才得到计算结果。

第二个函数async function testResult()是一个异步函数。假如仅声明一个函数是async,而不用await,这其实和一般顺序函数是没有区别的。同理,仅在一句代码中加await,而不将对应函数声明成async的,也和顺序函数没区别,但es6语法中规定单用await没有意义,故await无法单独出现。上面的例子中async和await配套使用了。

这里await的作用,顾名思义就是等待doubleAfter2seconds(30)的返回结果,这里double函数内部模拟复杂逻辑耗时2000ms,故let result = 60(其实这里的60应该是一个promise对象,还是暂不考虑promise) 需要2000ms后才接受到结果60。await会block住对应的async函数,将异步函数放到浏览器队列中(js本身是单线程的,而c#是真正的多线程),让浏览器栈处理,主线程继续走主逻辑,主逻辑完成后,js对队列进行轮询,有结果则取回渲染,没有结果则重新放到队尾。js将自己一块内存共享给浏览器,用于接收异步的返回结果。轮询就是轮询这块共享内存。

所以输出结果:首先输出“外部调用前”,然后进入异步函数async testResult(),正常输出第一句“内部调用前”,紧接着result开始await结果60,整个testResult()函数被block住,交给浏览器运行。同时,主线程接着往下走,打印“外部调用后”。2000ms过后,result接收到结果60,testResult()继续往下走,打印出result:60,最后打印“内部调用后”。

结果:

// 外部调用前
// 内部调用前
// 外部调用后
// 60
// 内部调用后 

回头来看一下promise的事情。let result 接收的其实不是60这个数字,而是一个promise对象,这个promise对象里面resolve的值是60

new Promise((resolve, reject) => {})

async/await是Promise的语法糖 <==> async和await是处理then链的语法糖,

这两句话是一样的。

语法糖:为了写法好看,async/await 像糖一样甜,但本质还是then链那一套。

then: (ref:js中then()的用法_dxyzhbb的博客-CSDN博客_js then

then()方法是异步执行

意思是:就是当.then()前的方法执行完后,再执行then()内部的程序,这样就避免了数据没获取到的问题,语法如下:

promise.then(onCompleted, onRejected); // 对应上面promise的resolve和reject

其中,onCompleted是成功时运行的函数,onRejected是拒绝时运行的函数,onCompleted是必须的,onRejected是可选的。

举例:
 

navigator.mediaDevices.getUserMedia(constrains).then(
     function (stream) {
         video.srcObject=stream;
     }
)
可以理解成navigator.mediaDevices.getUserMedia(constrains) 返回一个参数stream,且返回成功了,然后执行function功能。

Then链的写法:(ref:【学习笔记】深入理解async/await - 唐吉sir - 博客园 (cnblogs.com)

/**
 * 假设一个业务,分多个步骤完成,每个步骤都是异步的
 * 而且后一步依赖于上一个步骤的结果
 * 我们仍然用setTimeout来模拟异步操作
 */
function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}

function step1(n) {
    console.log(`step1 : ${n}`);
    return takeLongTime(n);
}

function step2(n) {
    console.log(`step2 : ${n}`);
    return takeLongTime(n);
}

function step3(n) {
    console.log(`step3 : ${n}`);
    return takeLongTime(n);
}

function doIt(){
    console.time('doIt');
    let time1 = 300;
    step1(time1)
        .then((time2) => step2(time2))
        .then((time3) => step3(time3))  
        .then((result) => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        })
}

doIt();

es6箭头函数:

// 参数=>表达式(函数体)  ,箭头函数
x => x * x
// 等价于(也是一种语法糖)
function (x) {
   return x * x;
}

async/await的写法:

async function doIt() {
    console.time('doIt');
    let time1 = 300;
    let time2 = await step1(time1);//将Promise对象resolve(n+200)的值赋给time2
    let time3 = await step1(time2);
    let result = await step1(time3);
    console.log(`result is ${result}`);
    console.timeEnd('doIt');
}

doIt();

后者就是前者的语法糖写法,本质并无区别。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值