美文网首页
异步、单线程、非阻塞、回调

异步、单线程、非阻塞、回调

作者: 林立镇 | 来源:发表于2017-08-16 23:12 被阅读0次

异步

先看一下下面对async、defer的介绍
下面的内容是文章《异步vs延迟属性》里的内容

<script>

我们首先定义什么<script>没有任何属性。HTML文件将被解析,直到脚本文件被命中,在这一点解析将停止,并将请求获取文件(如果它是外部的)。然后在执行解析之前执行该脚本。

image.png
<script async>

async 在HTML解析过程中下载文件,并在完成下载后暂停HTML解析器执行。

image.png
<script defer>

defer在HTML解析过程中下载文件,只有在解析器完成后才能执行该文件。defer脚本也可以按照它们在文档中出现的顺序执行。

image.png
什么时候应该用什么?

通常你想async在可能的地方使用,defer然后没有属性。以下是一些一般规则:

  • 如果脚本是模块化的,并且不依赖于任何脚本然后使用async。
  • 如果脚本依赖或被另一个脚本依赖,那么使用defer。
  • 如果脚本很小并被脚本依赖,async那么请使用内置的脚本之上的script任何属性。
async支持

IE9及以下版本的执行有一些非常糟糕的错误,defer以致执行顺序不符合要求。如果您需要支持<= IE9,我建议不要使用defer,如果执行顺序很重要,请将脚本包含在没有属性的位置。

单线程

因为js运行在浏览器中,是单线程的,每个window一个JS线程
既然是单线程的,在某个特定的时刻只有特定的代码能够被执行。
而浏览器是事件驱动的(Event driven),浏览器中很多行为是异步(Asynchronized)的,会创建事件并放入执行队列中。
javascript引擎是单线程处理它的任务队列,你可以理解成就是普通函数和回调函数构成的队列。
当异步事件发生时,如鼠标点击事件发生、定时器触发事件发生、XMLHttpRequest完成回调触发等,将他们放入执行队列,等待当前代码执行完成。

异步事件驱动

前面已经提到浏览器是事件驱动的(Event driven),浏览器中很多行为是异步(Asynchronized)的,
例如:鼠标点击事件、窗口大小拖拉事件、定时器触发事件XMLHttpRequest完成回调等。
当一个异步事件发生的时候,它就进入事件队列。浏览器有一个内部大消息循环,Event Loop(事件循环),会轮询大的事件队列并处理事件。
例如,浏览器当前正在忙于处理onclick事件,这时另外一个事件发生了(如:window onSize),这个异步事件就被放入事件队列等待处理,只有前面的处理完毕了,空闲了才会执行这个事件。
setTimeout也是一样,当调用的时候,js引擎会启动定时器timer,大约xxms以后执行xxx,
当定时器时间到,就把该事件放到主事件队列等待处理(浏览器不忙的时候才会真正执行)

异步示例——事件
var items
var i
document.body.innerHTML = `
    <ol>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ol>         
` 
items = document.querySelectorAll('li')
for(i=0;i<items.length;i++){
    items[i].onclick = function(){
        console.log(i)
    }
}
image.png

函数解析后,不会马上执行
等鼠标点击有序列表项,
才会执行,
无论是哪一项都会在控制台打出‘5’。
因为绑定事件的处理函数,
等输入流给出事件触发信号,
才会执行函数。
但是,
其它的代码会继续解析并执行。
所以,
变量i的值继续增在,增加到5,
这时候事件还没触发,所以函数也不会执行,
等它执行时,
获取的变量i已经是‘5’了

异步示例——定时器
var a = 1
setTimeout(function(){
    var a = 2
    console.log(a)
},1000)
console.log(a)
1
undefined
//一秒之后才打出‘2’
2

上面,先打出1
说明,全局环境里console.log(a)这一行代码会先执行,
然后再打出‘2’,
说明,setTimeout()里的console.log(a)
虽然先被浏览器解析,
但是要等1秒之后,IO输入流才给它一个信号说一秒时间到了,
才会执行了

异步示例——请求

data.json

{"name":"llz"}

javascript

var a = 1
var xhr = new XMLHttpRequest()
xhr.open('GET','/data.json')
xhr.onload = function(){
console.log(xhr.responseText)
}
xhr.send()
console.log(1)

console

1
{"name":"llz"}

控制台,会先打出1,
等请求的数据下载完后,
才会打出请求的数据‘{"name":"llz"}’
说明请求也是异步

非阻塞js的实现(non-blocking javascript)

js在浏览器中需要被下载、解释并执行这三步。在html body标签中的script都是阻塞的。
也就是说,顺序下载、解释、执行。尽管Chrome可以实现多线程并行下载外部资源,
例如:script file、image、frame等(css比较复杂,在IE中不阻塞下载,但Firefox阻塞下载)。
但是,由于js是单线程的,所以尽管浏览器可以并发加快js的下载,但必须依次执行。
所以chrome中image图片资源是可以并发下载的,但外部js文件并发下载没有多大意义。

回调

回调 == 异步 + 函数调用

回调示例——定时器
function asyncFn(fn){
    setTimeout(function(){
        fn(Math.random())
    },(2*Math.random()*3)*1000)
}
asyncFn(function(xxx){
    console.log('xxx is ')
    console.log(xxx)
})

等了将近5秒钟,才打出下面的代码

xxx is 
0.5311492544878877

我们可以看出,setTimeout造成了异步,
等5秒后,作为函数asyncFn参数的函数才调用

回调示例——请求

案例我放在github上
回调函数实例源码
案例里的原理是,
在javascript里声明一个函数callbakFn
然后发出一个请求,将函数名作为参数传进去xxx.js?callback=callback
同时请求xxx.js文件,
在服务器里文件server.js将函数名callbakFn替换xxx.js文件里字符串{{callback}}
xxx.js文件,就变成

callbackFn('回调成功')

然后浏览器下载xxx.js文件,解析指向上面的代码,
就会调用callbackFn函数,
这就是请求里的回调。

相关文章

  • 异步、单线程、非阻塞、回调

    异步 先看一下下面对async、defer的介绍下面的内容是文章《异步vs延迟属性》里的内容 我们首先定义什么 没...

  • 深入浅出Node.js_异步编程

    Node 的特点:事件驱动、非阻塞I/O 异步I/O; 事件(轻量级、松耦合、只关注事务点)与回调函数; 单线程:...

  • 进程 线程 协程 同步 异步 阻塞 非阻塞

    参考文章: Python 中的进程、线程、协程、同步、异步、回调 简明网络I/O模型---同步异步阻塞非阻塞之惑...

  • 同步/异步、阻塞/非阻塞

    我们常说 JavaScript 是单线程、异步、非阻塞的,但实际上同步/异步、阻塞/非阻塞这两组概念并非那么简单。...

  • 同步,异步,阻塞,非阻塞, 回调

    1.基本概念 引子以ajax为例: 异步就是不等待结果的代码, 异步并不是同时做两件事情 一个小故事:小A烧开水。...

  • Node事件回调

    1.什么是回调2.什么是同步/异步3.什么是I/O4.什么是单线程/多线程5.什么是阻塞/非阻塞6.什么是事件7....

  • 回调函数

    异步编程依托于回调函数来实现,但不是说使用了回调函数之后程序就异步化了。 创建文件 input.txt: 非阻塞模...

  • 笔记:Promise的使用

    ES5的回调地狱问题: 大家都知道,ES5里面我们处理异步请求的时候会通过callback回调函数来解决异步非阻塞...

  • Node.js 调用栈

    Node.js 是异步非阻塞I/O的。如何解释 Node.js 即是单线程又是异步且非阻塞I/O的,需要理解 No...

  • 同步与异步、事件循环与消息队列、微任务与宏任务

    JavaScript 是单线程、异步、非阻塞、解释型脚本语言。 单线程与多线程 单线程语言:JavaScript ...

网友评论

      本文标题:异步、单线程、非阻塞、回调

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