JS中的同步异步

作者: 临安linan | 来源:发表于2019-05-09 10:24 被阅读9次

目录

1. 在JS中,什么是同步异步?
2. JS中常见的异步代码

1. 在JS中,什么是同步异步?

通俗解释一下,同步与异步:

异步:不等待结果就执行接下来的代码,一句话:不等结果!
同步:等待异步代码执行完毕后才执行接下来的代码,一句话:等结果!
先来看一段同步代码

console.log(1)
sleep(3)  // 这里让控制台睡3s
console.log(2)  // 这里的2会在3s后被打印出来

同步会等待sleep(3)执行完毕后才执行后面的代码
再来看一段异步代码

console.log(1)
setTimeOut(function(){console.log('3秒结束')},3000)
console.log(2)  // 不等定时器,直接打印2
// 3s结束后才打印'3秒结束'

但是为啥JS是单线程的,却能实现异步代码呢?

其实上面的异步代码,在定setTimeOut闹钟时,JS引擎是委托了浏览器来监听这3s的等待,所以JS引擎的进程就空闲了,console.log(2)就能立刻执行。

而JS引擎在执行同步代码时,进程会一直堵塞,无法执行后面的代码。

2. JS中常见的同步异步代码

(1)获取图片宽度为0

var img = document.getElementsByClassName('img')[0].width  // width为0
// 图片加载的时候,可能尚未加载完就已经执行了JS代码

解决办法

img.onload = function(){
  // 在这里面获取宽度
}

(2)for循环点击li打印索引

let liList = document.getElementsByTagName('li')  // 假设有5个li元素
for(let i = 0; i < liList.length; i ++){
  liList[i].onclick = function(){
    console.log(i)  // 期望打印出0,1,2,3,4。实际打印出来5个5
  }
}

for循环中,每次循环都给li绑定一个点击事件,console.log(i)中的i是同一个i,在for循环结束时,i === 5,同时绑定了如下点击事件

liList[0].onclick=function(){console.log(i)}
liList[1].onclick=function(){console.log(i)}
liList[2].onclick=function(){console.log(i)}
liList[3].onclick=function(){console.log(i)}
liList[4].onclick=function(){console.log(i)}  // 注意打印的都是i,不是对应的0,1,2,3,4!
// 然鹅当用户点击li的时候,for循环已经执行完了,i已经变成5了

解决方法

  1. for循环中用 let 代替 i ,使每次迭代的 i 都不一样
  2. 用立即执行函数
let liList = document.getElementsByTagName('li')  // 假设有5个li元素
for(let i = 0; i < liList.length; i ++){
  !function(i){
    // 由于函数立即执行,会传进来对应的i
    liList[i].onclick = function(){
      console.log(i)  // 期望打印出0,1,2,3,4。实际打印出来5个5
    }
  }(i)
}

(3)AJAX
应该没人会发同步ajax吧......,万一请求不成功,JS引擎的进程就会一直被堵塞。
(4)Promise中 .then 的回调
为什么说Promise中 .then 的回调函数是异步的?来看一段代码:

promise.then(function(){ 
  if (flag) { 
    foo(); 
  } else { 
     setTimeout(function(){ 
        foo(); 
     }) 
  } 
});
bar();

我们来看下 bar 和 foo 的执行顺序
如果 then 回调是同步的

flag 为真时,foo 先执行,然后执行bar。(bar会等上面promise代码的执行结果,执行完了才走到bar)
flag为假时,bar先执行,foo后执行。(bar会等上面promise代码的执行结果,但是执行到setTimeOut时,由于setTimeOut是异步的,所以bar就不等了,所以先执行bar)

如果 then 回调是异步的

很明显,在promise发送请求时,bar 就已经请求了,代码执行顺序必定是先 bar 后 foo。

Promise为了保证代码的执行顺序永远保持一致,所以 then 回调采用了异步

相关文章

  • JS中的同步异步

    目录 1. 在JS中,什么是同步异步? 2. JS中常见的异步代码 1. 在JS中,什么是同步异步? 通俗解释一下...

  • js加载同步还是异步? JSONP原理?

    1、浏览器端的js加载默认是同步还是异步?同步,可以人为设置异步;async让js异步加载,需要每个script标...

  • 简述JS执行机制 Event Loop

    1.同步异步 JS是单线程的,由上至下排队执行任务代码。为了提高JS的性能又区分为 同步任务 和 异步任务。同步任...

  • javascript的同步异步编程

    js中的同步和异步 同步js是单线程的,浏览器只会分配一个js引擎线程,用来执行js代码,当其执行代码时,js一次...

  • 【Node.js】读取文件

    在node.js里,读取文件分为 同步读取 和 异步读取。 同步读取: fs.readFileSync() 异步读...

  • JS中的同步和异步

    JS是单线程的同步:指的是等待一件事情完成之后才会去执行下一件事,JS中大部分都是同步编程。循环就是同步的,所以在...

  • js中的同步与异步

    前言 在平日的编码中,你能列出你常用的异步编码?怎么理解同步与异步? 如果仅仅停留在文字上的理解,个人觉得有口无心...

  • JS中的同步和异步

    一、同步 01 什么是同步同步就是一个人同一时间只能做一件事情,只有一件事情做完,才能做另外一件事情。如果有多个事...

  • JS中的同步与异步

    首先,js是单线程的,这一点毋庸置疑。 同步异步的概念:同步:大家按照顺序,你运行完我运行,不存在你我同时运行的情...

  • js中的同步和异步

    一、单线程 (1)单线程的概念 如果大家熟悉java,应该都知道,java是一门多线程语言,我们常常可以利用jav...

网友评论

    本文标题:JS中的同步异步

    本文链接:https://www.haomeiwen.com/subject/apnboqtx.html