重新认识javascript的settimeout和异步
今晚看到QLeelulu的一道JavaScript面试题(setTimeout),稍微想了一下,好不容易连猜带蒙,凑巧说对了答案。但是原因到底是什么呢?自己一时也说不太清楚,反正感觉就是一个死循环造成的。然后看了一下文章下面的评论,发现5楼和6楼的回答很有道理,主要意思就是说javascript引擎是单线程执行的,while循环那里执行的时候,settimeout里面的函数根本没有执行的机会,这样while那里永远为真,造成死循环。但是单纯看还是不怎么踏实,最后发挥实践精神,自己动手做了两个实验:
1、简单的settimeout
setTimeout(function () { while (true) { } }, 1000);setTimeout(function () { alert('end 2'); }, 2000);setTimeout(function () { alert('end 1'); }, 100);alert('end');
执行的结果是弹出‘end’‘end 1’,然后浏览器假死,就是不弹出‘end 2’。也就是说第一个settimeout里执行的时候是一个死循环,这个直接导致了理论上比它晚一秒执行的第二个settimeout里的函数被阻塞,这个和我们平时所理解的异步函数多线程互不干扰是不符的。
2、ajax请求回调
接着我们来测试一下通过xmlhttprequest实现ajax异步请求调用,主要代码如下:
var xmlReq = createXMLHTTP();//创建一个xmlhttprequest对象function testAsynRequest() {var url = "/AsyncHandler.ashx?action=ajax";xmlReq.open("post", url, true);xmlReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");xmlReq.onreadystatechange = function () {if (xmlReq.readyState == 4) {if (xmlReq.status == 200) {var jsonData = eval('(' + xmlReq.responseText + ')');alert(jsonData.message);}else if (xmlReq.status == 404) {alert("Requested URL is not found.");} else if (xmlReq.status == 403) {alert("Access denied.");} else {alert("status is " + xmlReq.status);}}};xmlReq.send(null);}testAsynRequest();//1秒后调用回调函数while (true) {}
在服务端实现简单的输出:
private void ProcessAjaxRequest(HttpContext context){string action = context.Request["ajax"];Thread.Sleep(1000);//等1秒string jsonObject = "{\"message\":\"" + action + "\"}";context.Response.Write(jsonObject);}
理论上,如果ajax异步请求,它的异步回调函数是在单独一个线程中,那么回调函数必然不被其他线程”阻挠“而顺利执行,也就是1秒后,它回调执行弹出‘ajax’,可是实际情况并非如此,回调函数无法执行,因为浏览器再次因为死循环假死。
结论:根据实践结果,可以得出,javascript引擎确实是单线程处理它的任务队列(能理解成就是普通函数和回调函数构成的队列吗?)的。在javascript里实现异步编程很大程度上就是一种障眼法,单线程的引擎实现多线程的编程,如果要实现一些资源同步互斥之类的操作(一如C#、Java等语言的多线程),我感觉真正实现起来根本无法轻易得到保证。
补充:如何实现javascript的sleep呢?在stackoverflow上找到一篇javascript sleep,试了一下,效果是有了,但是执行的时候cpu很高,真还不如直接settimeout呢。
重新认识javascript的settimeout和异步相关推荐
- C# Task 循环任务_聊聊 JavaScript 的并发、异步和事件循环
本文作者:Cody Chan,题图来自 Jake Archibald JavaScript 作为天生的单线程语言,社区经常聊 JavaScript 就聊异步.聊 Event Loop,看起来它们好像难 ...
- JavaScript 循环中调用异步函数的三种方法,及为什么 forEach 无法工作的分析
JavaScript 循环中调用异步函数的三种方法,及为什么 forEach 无法工作的分析 业务分析 初版的问题 解决方案 传统的 for 循环 不使用 for 循环的解决方案 分析 forEach ...
- javascript 权威指南第7版_第七版 JavaScript 权威指南之异步
一些计算程序,比如科学模拟和机器学习模型,是计算密集型[compute-bound]的.它们不间断地运行直到得到结果. 大多数现实世界的程序,则是异步的.浏览器里的 JavaScript 程序是典型的 ...
- [转]掌握Ajax 第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求 [IBM]
转自:http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/ 掌握 Ajax,第 2 部分: 使用 JavaScript 和 Ajax 发出异步 ...
- javascript中setTimeout()函数
javascript中setTimeout()函数 大家都知道javascript中的setTimeput()函数的作用,一般会用他来处理一些连续的事情,们先看一个例子: <head> ...
- 掌握 Ajax,第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求
转http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/ 掌握 Ajax,第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求 ...
- AJAX工作原理及其优缺点 1.什么是AJAX? AJAX全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML),是一种创建交互式网页应用的网页
参考文章:https://www.cnblogs.com/SanMaoSpace/archive/2013/06/15/3137180.html AJAX工作原理及其优缺点 1.什么是AJAX? AJ ...
- JavaScript———从setTimeout与setInterval到AJAX异步
setTimeout与setInterval执行 首先我们看一下以下代码打印结果 1 2 3 4 5 6 7 console.log(1); setTimeout(function() { conso ...
- JavaScript单线程 setTimeout定时器
理解JavaScript的单线程的理念对于JavaScript学习,以及掌握其中的一些设计机制非常重要,比如回调.定时器.对于后续学习NodeJS也有很大的帮助. 通过先demo,后总结的形式,使得J ...
最新文章
- mysql 关联关系
- Oracle发布开源的轻量级 Java 微服务框架 Helidon 1
- filebeat+elk简单搭配
- 19年8月 字母哥 第二章 RESTFul接口实现与测试 看到这里了
- 设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动
- mysql怎么拆字符串_MySQL截取和拆分字符串函数用法示例
- SpringBoot应用部署[转]
- Linux系统中用stat命令查看文件的三个时间属性
- Java中使用poi导入、导出Excel
- 阿里云推出企业级智能协同办公方案 云桌面、云AP、云客服一应俱全
- python缩进格式错误修改_Python,意外的缩进错误解析,Pythonunexpectedindent,解决,方法...
- linux的make命令是什么,Linux中make, make install命令分别是什么
- 10、斐波那契数列,跳台阶问题(Python)
- GitHub客户端上传本地代码
- 717 1比特与2比特字符
- 此更新不适用您的计算机 win10,高手亲自讲解Win10系统提示此更新不适用于您的详尽处理办法...
- Ubuntu 20.04 实现Windows 复制粘贴
- Python金融数据挖掘 第八章 第1节 Apriori算法原理(2)
- pycharm 第三方库加载不出来
- 仪器仪表应用,国产IC用于替代AD7792,AD7793的型号分享,完全P=P