文章目录

  • 1.前言
  • 2.await是否阻塞主线程?
  • 3.await是否同步?
  • 4.总结

1.前言

这篇文章我是不想写的,因为之前已经写过了(异步回调Async Await与Promise区别),此时此刻的心情是非常的不满,为什么呢? 因为前几天项目中把多层promise链式回调用了用 es6的await改写了,当我们前端XXX看到之后很疑惑,就问,为什么这么写?你知道await是什么吗?我说知道,await后面是返回的一个promise的resolve/reject的结果,这样的目的可以避免很多promise链式嵌套回调,而且await 的promise不执行完,下面代码也不会执行!代码看上去也很同步,他很不屑的看了我一眼,别一知半解的在那乱用(我们公司的领导说话口气都这样),别以为我不懂,这个await就是等待的意思!它就是个同步代码,会阻塞主线程,以前写什么XXX的时候,用这个会导致浏览器卡死不动,在后端服务器会直接DOWN掉,不知道不要乱用?,其实我很想解释,但是我觉得当时的情况,我多说无益,其实我这样写也是为了让代码更加清晰,以后维护起来也方便!无奈之举!只能改回promise的链式嵌套写法,这篇文章我会分析下我对await(一知半解)的理解!

2.await是否阻塞主线程?

先说下 await的正确使用,await必须是在这个async声明的函数内部使用,async是什么意思?异步的意思,看到这个东西也知道这个是个异步的函数,会阻塞主线程?,javascript虽然是单线程,先执行同步代码,碰到异步函数的会扔进异步队列里面,等主线程空闲了再把异步队列再把异步函数放进主线程执行,下面我来证实下我的观点

let test = async () =>{return await new Promise((resolve, reject)=>{setTimeout(() =>{resolve("第一个请求")console.log("第一个请求")}, 5000)});
}test();for (let i = 0; i < 10; i++) {setTimeout((i) =>{console.log("我执行了" + i + "次")}, 1000 * i, i);
}

按正常执行顺序,主线程执行到test函数时,如果是同步的,那么下面的for循坏更本不会执行!我们来看执行结果


结论:所以可以跟明确的得出结论,它不会阻塞主线程!

3.await是否同步?

首先要明白await的用法,当await后面的不是promise,它会不会阻塞?看下面代码!

function forLoop() {for (let i = 0; i < 10; i++) {setTimeout((i) =>{console.log("我执行了" + i + "次")}, 1000 * i, i);}
}let test = async () => {await forLoop();console.log("我执行不执行");
}
test();

await 后面不是个promise,而是个for循环,里面有个setTimout,这个又涉及到宏任务了(先不管,暂且他看成异步),那么await 后面接到一个异步setTimout的函数,那么我下面的 console.log还会执行吗?还是会卡在这里,等setTimout函数执行完再执行呢?让结果来告诉我们!

结论:如果await后面接的不是promise,那么它是按正常顺序执行的,先同步后异步,需要注意的await后面属于微任务,所以,这种情况也不会阻塞

如果await 后面接的是promise,那么await后面的代码就相当在promise.then()里面执行,promise.then里面是个微任务如果不懂可以点击javascript执行机制所以我们来看下例子回忆下

setTimeout(() => {console.log("setTimeout宏任务")
}, 0);let test = async () =>{console.log("promise 同步代码1")let onePromise = await new Promise((resolve, reject) => {resolve("success")});console.log("promise微任务执行2");
}test();new Promise((resolve, reject) => {console.log("promise 同步代码")resolve("success");
}).then((data) => {console.log("promise微任务执行1")
})
console.log("end");

简单分析下,一开始setTimeout宏任务扔进任务队列,接着执行console.log("promise 同步代码1"), console.log("promise微任务执行2")是在promise.then中执行的所以是个微任务扔进任务队列,接着执行 console.log("promise 同步代码"), 又一个 console.log("promise微任务执行1") 微任务扔进任务队列,接着执行console.log("end"),看下任务队列有没有微任务,按顺序执行 console.log("promise微任务执行2"),再执行 console.log("promise微任务执行1"),最后执行下一轮事件循环,执行 console.log("setTimeout宏任务"),后面没有微任务了,结束事件循环!

let test = async () => {let onePromise = await new Promise((resolve, reject) => {resolve("success")});let result = "promise微任务执行2" ;console.log(result);
}test();//等价于let test = async () => {let onePromise = await new Promise((resolve, reject) => {resolve("success")});
}
test().then((data)=>{let result = "promise微任务执行2" ;console.log(result);
});

await 后面的执行都相当于放到了Promise.resolve(),很显然是成功的回调函数!那么多个await呢?我们来模拟下

let asyncFn1 = async () => {await new Promise((resolve, reject) => {resolve("success1")console.log("success1");});await new Promise((resolve, reject) => {resolve("success2")console.log("success2");});await new Promise((resolve, reject) => {resolve("success3");console.log("success3");});
}
asyncFn1();//等价于let asyncFn1 = async () => {await new Promise((resolve, reject) => {resolve("success1")console.log("success1");});
}
asyncFn1().then((data) => {let asyncFn2 = async () => {await new Promise((resolve, reject) => {resolve("success2")console.log("success2");});}asyncFn2().then(() => {let asyncFn3 = async () => {await new Promise((resolve, reject) => {resolve("success3")console.log("success3");});}asyncFn3().then(() => {})});
});

看上面这种代码转变,那么你应该知道这个和promise链式调用有没有什么区别?为什么es6要出async,await,就是为了解决这种多个promise链式调用嵌套的,它是promise的升级版!只是在promise原有的基础上升级了,让我们调用的时候代码看起来更清晰!

let asyncFn1 = async () => {let onePromise = await new Promise((resolve, reject) => {setTimeout(function () {resolve("第一个请求");console.log("第一个请求");}, 5000)});console.log("我要先执行");
}asyncFn1();

像上面这种写法是有问题,要等onePromise 执行完成之后才会执行下面的,但是你别忘记了await的初衷,你肯定不会愚蠢到把先要执行的东西放到一个promise的回调里面吧

结论:如果await后面接的是promise,那么它是严格按照代码顺序执行的,此时是同步的,因为后面的代码都是promise的成功回调

4.总结

await不会阻塞主线程,不会导致浏览器假死,卡死,anync是个异步函数,会被放进异步队列,等主线程空闲了才会放进主线程,await后面的代码如果是promise,那么是同步的,如果不是promise,那么执行规则是先同步后异步,但是你要了解await,它是为了解决promise链式调用嵌套而存在的,就算是promise链式嵌套,它的执行也是同步!所以要在合适的使用场景正确使用!(你可能写个循环都会出现死循环导致浏览器崩溃)

被说一知半解,await不懂你别乱用相关推荐

  1. 老板和主管不懂SEO,乱给SEO人员下指令怎么办?

    问题:老板和主管不懂SEO,乱给SEO人员下指令怎么办? 答:这种现象很普遍,因为大部分老板招SEO人员是要花成本的,所以难免会着急,可能就会乱请教一些所谓的"SEO高手"或者自己 ...

  2. m.2接口和nvme区别_M.2接口硬盘当真速度就快吗?这些不懂就别乱买!今天再说一遍...

    硬盘是电脑中的存储硬件,也是电脑中核心的硬件之一,它的主要作用就是存储系统.软件.文件的重要作用,目前市场上有机械硬盘.机械固态混合硬盘.固态硬盘三大类,机械硬盘具有容量大,读写速度慢的特点:混合硬盘 ...

  3. python转go感觉难_读《我为什么从python转向go》的一些感受

    一开始我以为是一篇2013年的老帖子,没想到竟然是2015年.不懂Python不要乱喷啊.你直接说"我不懂Python,我也不愿意维护前任写的糟糕代码,我Go牛B,所以我要重构一遍!&quo ...

  4. C++ 0x: 内存模型

    2019独角兽企业重金招聘Python工程师标准>>> 自C++11有了多线程,自然 原子类型(atomic)也是少不了的. 提到原子类型必然是与内存模型(std::memory_o ...

  5. 对云风 cstring 第二次解析

    前言 从明天起 关心粮食和蔬菜 我有一所房子 面朝大海 春暖花开 本文前提条件 1.了解 posix 线程 2.了解 原子操作 3.具备简单C基础,或者 你也敲一遍. 如果上面不太清楚,你可以翻看我以 ...

  6. 鸡蛋该放在哪些篮子里?多少合适?

    这篇文章是接着前面<IT人士如何避免中年危机?>和<我所参加的最贵的培训>的思路来的. <IT人士如何避免中年危机?>讨论了价值投资的必要性,并给出了方法论: 找到 ...

  7. 票务系统思维导图_最全思维导图分享,告诉你如何系统的学好软件测试。

    用一张图告诉你软件测如何学,如何系统的学,如何学得更好.全篇干货,值得收藏,希望可以帮到大家. 开始分享之前,先发个牢骚,经常看到有人在讲软件测试简单,我就呵呵了,不懂就别乱下结论,真正能把软件测试给 ...

  8. 程序员必备技能-科学砍需求

    作为码农在电商圈.O2O.互金行业和产品需求纠缠了多年,做过一些好的产品需求,也做过很多失败的产品需求,好的产品需求即使不成也未尝不是一种探索尝试,结果应该是让人有所收获的.好的产品逻辑清晰,产品价值 ...

  9. windows文件路径 正则表达式_Windows非常实用的四款软件

    Windows非常实用的四款软件 for挨踢世界 Windows非常实用的四款软件 买一个电脑,进入一个公司,每天学习办公,各种辅助软件少不了!还有就是一些让你提高工作效率的软件,比如: Everyt ...

最新文章

  1. C++:随笔6---new\delete\虚方法\抽象方法
  2. Nhibernate 3.0 cookbook学习笔记 一对多与多对多映射
  3. 单源最短路——dijkstra算法
  4. MATLAB从入门到精通:基本矩阵运算-矩阵的基本方法和函数
  5. Project Server的页面如何修改Text
  6. dedecms右侧悬浮_织梦dedecms网站上添加漂浮广告
  7. linux waitpid子进程,关于waitpid()函数的问题,为什么最后子进程没退出来啊?...
  8. 【转载】Linux下rz,sz与ssh的配合使用
  9. Cameralink视频数据信号
  10. 宇枫资本投资理财投资入门与技巧
  11. 【OpenCV】尺寸测量
  12. 和平精英服务器为什么老是无响应,和平精英触控失灵怎么回事 操作触屏有时候没反应介绍...
  13. enumerate() 函数的解释
  14. 网易云的特色与优势?|网易云
  15. 学习毅力篇:学习拖拖拉拉?3招治愈拖延症!
  16. Ubuntu搭建服务器
  17. Linux内核的5个子系统
  18. dellR720xd服务器做raid安装操作系统
  19. matlab平坦衰落,平坦衰落信道的MATLAB仿真
  20. 股妖APP也妖 -- 与暴风魔镜相关

热门文章

  1. js判断PC端或是移动端、判断是不是微信浏览器、js代码判断浏览器种类IE、FF、Opera、Safari、chrome及版本
  2. openssl C++ DSA对指定文件内容签名和解签
  3. yolo-fastestv2 训练部署流程
  4. FLASH场景的片头loading
  5. 击鼓传花问题——JS实现
  6. 达梦数据库课程干货分享LIKE、REGEXP_LIKE、INSTR的正确打开方式
  7. 【AI开源项目】深度学习工具一键抠图
  8. 电商网站logo常用实现方法HTML/CSS
  9. 家用计算机怎么更新,Win7家庭版如何升级为旗舰版
  10. 【Halcon视觉】标定