资讯专栏INFORMATION COLUMN

异步!异步!异步!

ThinkSNS / 1022人阅读

摘要:同步和异步先说个傻子的故事有个傻子,第一次用某雷下载大片,就是大人看的片,咳咳咳。。。

1.同步和异步 1.1先说个傻子的故事

</>复制代码

  1. 有个傻子,第一次用某雷下载大片,就是大人看的片,咳咳咳。。。
  2. 某雷告诉他,下载时间要俩小时,傻子心想,要俩小时呐,我第一次用某雷,我得盯着它下载,啥也不能干
  3. 于是傻子就干瞪着电脑,等着片下完,这俩小时,傻子啥也没干
  4. 后来,傻子变聪明了,他想,反正某雷在帮他下载,这俩小时,他完全可以干干其他事情啊,比如学学计算机知识呀等等
  5. 等某雷下完了,再回来看呗
  6. 于是傻子潜心研究计算机知识,直到有一天他看到了有关于异步的知识,突然间明白了

原来他等待某雷下完,啥也不干的过程就叫做同步
后来他在某雷下载过程中自学计算机知识的过程就叫做异步

1.2 同步与异步的概念

同步
英文:Synchronization
wiki解释:指在一个系统中所发生的事件(event),之间进行协调,在时间上出现一致性与统一化的现象。
是不是很难理解?
其实就是代码要等待到结果,才能继续进行【你可以理解为同步阻塞了代码继续执行】

异步
英文:Asynchronization【在同步前面加了个A】
wiki解释就不贴了,有兴趣的朋友可以自己搜索看一下,反正我看的也挺头疼
其实就是代码不用等待到结果,就能继续进行【你可以理解为异步不阻塞代码继续执行】
啥意思咧,让我们看个大家都见过的例子

</>复制代码

  1. function wait() {
  2. setTimeout(() => console.log(this), 3000)
  3. }
  4. wait() // 三秒钟后,得到结果
  5. console.log(1) // 如果没有异步的话,我得等三秒钟才能执行,所以,感谢异步
2.常见的异步问题 2.1图片加载问题

</>复制代码

  1. // 前提条件:用户的浏览器第一次请求这个图片,也就是用户的浏览器未缓存
  2. document.getElementsByTagNames("img")[0].width // 宽度为 0

为什么width会为0呢?
因为js运行的时候,img并没有下载完毕

解决方案

</>复制代码

  1. let imgNode = document.getElementsByTagName("img")[0]
  2. imgNode.addEventListener("onload",function () {
  3. console.log(this.width)
  4. })
2.2 面试题常考的异步问题

</>复制代码

  1. // 假设有5个li
  2. let liList = document.querySelectorAll("li")
  3. for (var i = 0; i < liList.length; i++) {
  4. liList[i].onclick = function () {
  5. console.log(i) // 5 5 5 5 5
  6. }
  7. }

为什么呢?
因为onclick事件是异步处理的,用户触发onclick事件时,循环早已结束,此时的i是5

解决方案一【立即执行函数创建独立作用域】

</>复制代码

  1. // 假设有5个li
  2. let liList = document.querySelectorAll("li")
  3. for (var i = 0; i < liList.length; i++) {
  4. !(function (j) {
  5. liList[j].onclick = function () {
  6. console.log(j) // 5 5 5 5 5
  7. }
  8. })(i)
  9. }

解决方案二【使用let】

</>复制代码

  1. // 假设有5个li
  2. let liList = document.querySelectorAll("li")
  3. for (let i = 0; i < liList.length; i++) {
  4. liList[i].onclick = function () {
  5. console.log(i) // 5 5 5 5 5
  6. }
  7. }
3.拿到异步结果的方式 —— 回调

请见回调是个什么鬼?

4.Promise

请见浅析Promise

5.async / await 语句 5.1 粗略了解await

mdn解释:await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用

</>复制代码

  1. 但是await究竟做了什么事情呢?

</>复制代码

  1. let setPromise = function () {
  2. return new Promise((resolve, reject) => {
  3. // 你的异步代码
  4. setTimeout(() => {
  5. resolve("success")
  6. }, 10000)
  7. })
  8. }
  9. let result = await setPromise()
  10. 如果你这个时候在控制台不断输入result。
  11. 控制台会不断地报错
  12. 控制台报错:result is not defined
  13. 直到10s后,才能成功

为啥报错呢?命名let result了呀
因为await在等待setPromise()完成后,才会执行let result =
也就是说await 让前面的 let 和 = 异步了

可能你会问:
这样一搞,result也异步了,那我岂不是还要回调?

</>复制代码

  1. 那么再来看下一个问题

</>复制代码

  1. let setPromise = function () {
  2. return new Promise((resolve, reject) => {
  3. // 你的异步代码
  4. setTimeout(() => {
  5. resolve("success")
  6. }, 10000)
  7. })
  8. }
  9. let result = await setPromise()
  10. console.log(1) // 请问这句代码是在10秒后被执行,还是立即执行?

答案:10s后执行

5.2 所以await究竟能干嘛

await改变了整个代码的执行顺序.
它可以让你用同步写代码的方式去写异步代码

5.3 那么async又是干啥的呢?

如果你在一个函数内使用了await,那么你最好在一个函数的前面加上async

</>复制代码

  1. let setPromise = function () {
  2. return new Promise((resolve, reject) => {
  3. // 你的异步代码
  4. setTimeout(() => {
  5. resolve("success")
  6. }, 2000)
  7. })
  8. }
  9. function test() {
  10. return result = await setPromise()
  11. }
  12. console.log(3)

控制台直接会报错:Uncaught SyntaxError: await is only valid in async function
啥意思咧 —— await只允许在 async function 内使用
也就是说,要在函数声明的时候就加上 async

</>复制代码

  1. async function test() {
  2. let result = await setPromise()
  3. }
5.4 Promise异步操作失败的情况

</>复制代码

  1. let setPromise = function () {
  2. return new Promise((resolve, reject) => {
  3. // 你的异步代码
  4. setTimeout(() => {
  5. reject.call(undefined)
  6. }, 2000)
  7. })
  8. }
  9. let result = await setPromise()
  10. console.log(result)
  11. // 浏览器又报错了 Uncaught (in promise) undefined

因为没有then/catch来处理Promise异步操作失败的结果
所以我们这次使用try...catch...语句

</>复制代码

  1. let setPromise = function () {
  2. return new Promise((resolve, reject) => {
  3. // 你的异步代码
  4. setTimeout(() => {
  5. reject.call(undefined)
  6. }, 2000)
  7. })
  8. }
  9. try {
  10. let result = await setPromise()
  11. console.log(result)
  12. } catch(rejected) {
  13. // 触发这一句
  14. console.log("error")
  15. }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93765.html

相关文章

  • JavaScript 异步时序问题

    摘要:异步时序问题吾辈的博客原文场景死后我们必升天堂,因为活时我们已在地狱。关键点异步操作得到结果的时间顺序是不确定的如果触发事件的频率较高异步操作的时间过长出现这种问题怎么解决既然关键点由两个要素组成,那么,只要破坏了任意一个即可。 JavaScript 异步时序问题 吾辈的博客原文:https://blog.rxliuli.com/p/de... 场景 死后我们必升天堂,因为活时我们已...

    tuantuan 评论0 收藏0
  • 同步与异步异步与回调

    摘要:同步与异步以上为同步代码,函数必须等函数执行完毕后才能执行。异步回调产生的结果就是,函数的调用并不直接返回结果,而往往是交给回调函数进行异步处理。 同步与异步: function a(){} function b(){} a(); b(); 以上为同步代码,函数b必须等函数a执行完毕后才能执行。 function a(){ ...

    dinfer 评论0 收藏0
  • 异步异步异步

    摘要:同步和异步先说个傻子的故事有个傻子,第一次用某雷下载大片,就是大人看的片,咳咳咳。。。 1.同步和异步 1.1先说个傻子的故事 有个傻子,第一次用某雷下载大片,就是大人看的片,咳咳咳。。。 某雷告诉他,下载时间要俩小时,傻子心想,要俩小时呐,我第一次用某雷,我得盯着它下载,啥也不能干 于是傻子就干瞪着电脑,等着片下完,这俩小时,傻子啥也没干 后来,傻子变聪明了,他想,反正某雷在帮他下...

    chanthuang 评论0 收藏0
  • (转)JavaScript:同步、异步和事件循环

    摘要:事件循环事件循环是指主线程重复从消息队列中取消息执行的过程。事件触发时,表示异步任务完成,会将事件监听器函数封装成一条消息放到消息队列中,等待主线程执行。 一. 单线程 我们常说JavaScript是单线程的。 所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个。不妨叫它主线程。 但是实际上还存在其他的线程。例如:处理AJAX请求的线程、处理DOM事件的线...

    android_c 评论0 收藏0
  • JavaScript:彻底理解同步、异步和事件循环(Event Loop)

    摘要:例如处理请求的线程处理事件的线程定时器线程读写文件的线程例如在中等等。事件循环事件循环是指主线程重复从消息队列中取消息执行的过程。事件触发时,表示异步任务完成,会将事件监听器函数封装成一条消息放到消息队列中,等待主线程执行。 一. 单线程 我们常说JavaScript是单线程的。 所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个。不妨叫它主线程。 但是实...

    wenyiweb 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<