`

js异步再看

 
阅读更多

之前有一篇《异步运行》,偶然写了一段代码对得到的结果不是很理解,重新查资料得到这篇文章。代码如下:

<body>
        this is test
	<script>
		setTimeout(function(){
			alert(100)
		},0);
	</script>
	<script type="text/javascript" src='http://china-addthis.googlecode.com/svn/trunk/addthis.js'></script>
//这里addthis.js的引用是比较耗时的
        <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
//这个引用是很快的
	<script>
		for(var i = 0;i<10000;i++){
			console.log(i);
		}
		alert(5)
	</script>

</body>

 这段代码的结果是:

①页面渲染出‘this is test’

②弹出100

③弹出5

如果把引入addthis.js这段代码注释掉那结果将会是:

①弹出5

②页面渲染出‘this is test’

③弹出100

为什么会出现这种结果呢?

 

接下来慢慢解释。

首先明确一点:JavaScript引擎是单线程运行的,浏览器无论在什么时候都只有一个线程在运行JavaScript程序

js设计成单线程的原因《异步运行》中讲过,那么单线程的JavaScript引擎是怎么配合浏览器内核处理定时器和响应浏览器事件等异步任务的呢?

 

浏览器内核允许多个线程异步执行,这些线程在内核控制下相互配合以保持同步。假如某一浏览器内核的实现至少有三个常驻线程:javascript引擎线程,界面渲染线程,浏览器事件触发线程,除这些外,还有一些执行完就终于的线程,如http请求线程,这些异步线程都会产生不同的异步事件,下面通过一个图来阐明单线程的JavaScript引擎与另外那些线程是怎样互动通信的。虽然每个浏览器内核实现细节不同,但这其中的调用原理都是大同小异

 

 

浏览器中的JavaScript引擎是基于事件驱动的,这里的事件可看作是浏览器派给他的各种任务,这些任务可以源自JS引擎当前执行的代码块,如调用setTimeout添加一个任务,也可来自浏览器内核的其他线程,如界面元素鼠标点击事件,定时触发器事件到达通知,异步请求状态变更通知等。从代码角度来看,任务实体就是各种回调函数,JS引擎一直等待着任务队列中任务的到来,由于单线程的关系,这些任务得进行排队,一个接着一个被引擎处理。

 

上图t1,t2...tn表示不同的时间点,tn下面对应的小方块代表该时间点的任务,假设现在是t1时刻,引擎运行在t1对应的任务方块代码内,在这个时间点内,我们来描述一下浏览器内核其他线程的状态

 

t1时刻:

GUI渲染线程:

该线程复制渲染浏览器界面HTML元素,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。GUI渲染线程跟JavaScript引擎线程是互斥的,这容易理解,因为JavaScript脚本可操纵DOM元素,在修改这些元素属性同时渲染界面,那么渲染前后获得的元素数据可能就不一致了。

在JavaScript引擎运行脚本期间,浏览器渲染线程都是出于挂起状态的,也就是被“冻结了”

所以,在脚本中执行对界面进行更新操作,如添加节点,删除节点或改变节点的外观等更新并不会立即体现出来,这些操作将保存在一个队列中,待JavaScript引擎空闲时才有机会渲染出来。

 

GUI事件触发线程:

JS脚本的执行不影响html元素事件的触发,在t1时间段内,首先是用户点击了一个鼠标键,点击被浏览器事件触发线程捕捉后形成一个鼠标点击事件,由图可知,对于JS引擎线程来说,这事件是由其他线程异步传到任务队列队尾的,由于引擎正在处理t1时的任务,这个鼠标点击事件正在等待处理

 

定时触发线程:

定时事件也是异步事件,它必须依赖外部来计时并触发定时事件。

上图所示,在t1任务执行的时间内,继鼠标点击事件触发后,先前设置的setTimeout定时也到达了,此刻对JS引擎来说,定时触发线程产生了一个异步定时事件并放到任务队列中,该事件被排到点击事件回调之后,等待处理。

同理,在t1任务执行时间内,setInterval定时器任务也被添加了

 

可见,假如t1任务执行时间非常长,远大于setInterval的定时间隔,那么定时触发器就会源源不断的产生异步定时事件并放到任务队列队尾而不管它们的‘前辈’是否已被处理。一旦前面的任务处理完,这些队列中的定时任务就不间断的被执行(而不会有时间间隔),这是因为,对于JS引擎来说,在处理队列中的各任务时处理方式都是一样的,只是处理的次序不同而已。

 

如果队列非空,引擎就从队列头取出一个任务,直到该任务处理完(即返回)后引擎接着取并运行下一个任务,在任务没返回前队列中的其他任务是没法被执行的

 

现在可以试着解释下文章开头的代码,这些代码每个部分都是有用的,包括for循环和两个js文件的引用

  • 大小: 63.5 KB
分享到:
评论

相关推荐

    Javascript异步编程(英文版)

    《JavaScript异步编程》这本书深入探讨了现代JavaScript开发中的关键主题——如何在不陷入混乱的情况下处理并发和并发任务。本书作者Trevor Burnham通过精确平衡的浏览器端和服务器端示例,为读者提供了一份简洁的...

    js 异步加载js, css文件

    当项目js(css)文件使用越来越多,js 文件的加载也成了性能上的一个问题,此资源能够在页面全部加载完成后异步加载js等资源文件,它可以顺序加载资源列表,也可以并发加载资源列表,它包含一个方法调用接口:...

    JS异步加载库

    JavaScript(JS)异步加载库是一种能够帮助开发者在网页中延迟加载或按需加载JavaScript资源的工具。这种库可以显著提高网页性能,减少首屏加载时间,优化用户体验,特别是对于那些依赖大量脚本的复杂应用而言。下面...

    JS异步加载图片

    在JavaScript(JS)中,异步加载图片是...通过以上介绍,我们可以了解到JavaScript异步加载图片的基本概念、实现方式以及优化策略。在实际开发中,根据项目需求选择合适的方法,可以有效提升网页的加载速度和用户体验。

    js异步加载.docx

    JavaScript 异步加载是网页优化的关键技术之一,它允许脚本在不阻塞浏览器解析页面的情况下进行下载和执行。在传统的同步加载模式下,JavaScript 文件的加载会暂停HTML的解析,直到该脚本完全下载并执行完毕。这可能...

    JavaScript异步编程g.pdf

    JavaScript异步编程是前端开发领域中的一个重要概念,它允许程序在等待长时间操作(如网络请求)时继续执行其他任务,而不是简单地暂停或停止,从而提升用户体验。本书《JavaScript异步编程》作为图灵程序设计丛书的...

    Javscript高性能编程+Javascript异步编程

    "JavaScript高性能编程"和"JavaScript异步编程"是两个关键的JavaScript专题,对于提升应用程序的性能和用户体验至关重要。 一、JavaScript高性能编程 1. **优化代码执行效率**:了解JavaScript引擎的工作原理,如...

    javascript异步调用库

    实现javascript异步调用 API: window.asyncall(function/functionName[,args,...][,function callback]) 参数说明: function/functionName:方法或方法名称 args:目标方法参数 callback:回调函数...

    《JavaScript异步编程》PDF版本下载.txt

    ### JavaScript异步编程知识点概述 #### 一、异步编程概念 在JavaScript中,异步编程是一种处理长时间运行操作而不阻塞主线程的方法。这种方式允许程序在等待某些操作(如I/O操作、网络请求等)完成的同时,继续...

    javascript异步编程 设计快速响应的网络应用 源码

    JavaScript异步编程是Web开发中的核心技能,它使得开发者能够设计出快速响应的网络应用,提供流畅...无论是在前端开发中处理AJAX请求,还是在Node.js后端处理I/O密集型任务,JavaScript异步编程都是不可或缺的一部分。

    js异步上传文件插件

    在IT行业中,JavaScript(简称JS)作为前端开发的主要语言,其异步上传文件的功能是现代网页应用中的一个重要组成部分。这个“js异步上传文件插件”涵盖了三种不同的异步上传方式,结合HTML、JS和Ajax技术,为开发者...

    js异步加载代码

    在"asyLoad.js"这个文件中,我们可以预期它包含了一段用于实现JavaScript异步加载的代码。下面将详细介绍异步加载的原理和常见实现方法。 1. **异步加载的原理**: - 使用`&lt;script&gt;`标签的`async`属性:当`async`...

    Javascript异步编程的4种方法

    ### JavaScript异步编程的四种方法 #### 概述 JavaScript是一种广泛使用的脚本语言,尤其在Web开发领域占据着核心地位。由于浏览器环境的限制,JavaScript最初被设计为单线程执行模型。这意味着在同一时间只能执行...

    js异步上传多张图片插件的使用方法

    在JavaScript中,异步上传多张图片是一种常见的需求,特别是在网页应用中,用户可能需要上传照片作为个人资料、产品图片等。本篇文章将详细介绍如何使用一个特定的js异步上传多张图片插件,帮助开发者实现这一功能。...

    再谈JavaScript异步编程

    在早期的JavaScript异步编程中,回调函数是处理异步操作的主要方式。然而,嵌套回调函数(俗称回调地狱)会导致代码难以阅读和维护。例如: ```javascript makeAjaxCall('***', (result) =&gt; { result = JSON.parse...

    深入理解JavaScript异步

    JavaScript异步编程是Web开发中的核心概念,尤其在构建高性能、响应式的网页应用时不可或缺。深入理解这一主题,对于任何JavaScript开发者来说都是至关重要的。在这个教程中,我们将探索JavaScript异步处理的各个...

    多图片js异步上传带预览demo源码

    在IT领域,尤其是在Web开发中,用户界面常常需要支持多图片的上传功能,这通常涉及到JavaScript(js)的异步处理技术。这个“多图片js异步上传带预览demo源码”提供了一个完整的解决方案,它包含了一系列关键知识点...

    php+js异步图片上传demo

    而异步上传则利用Ajax(Asynchronous JavaScript and XML,尽管现在通常不再涉及XML)技术,通过JavaScript创建后台通信,使得上传过程在后台进行,用户界面仍能保持交互性。 在这个"php+js异步图片上传demo"中,...

Global site tag (gtag.js) - Google Analytics