[Effective JavaScript 笔记]第61条:不要阻塞I/O事件队列
js程序是构建在事件之上的。输入可能来自不同的外部源。在一些语言中,我们习惯地编写代码来等待某个特定的输入。
var text=downloadSync('http://example.com/file.txt');
console.log(text);
像这样的形式downloadSync称为同步函数(或阻塞函数)。程序会停止做任何工作,而等待它的输入。在这个例子中,也就是等待从网络上下载文件的结果。由于在等待下载完成的期间,计算机可以做其他有用的工作,因此这样的语言通常为程序员提供一种方法来创建多个线程,即并行执行子计算。它允许程序的一部分停下来等待(阻塞)一个低速的输入,而程序的另一部分可以继续进行独立的工作。
在js中,大多的I/O操作都提供了异步的或非阻塞的API。程序员提供一个回调函数,一旦输入完成就可以被系统调用,而不是程序阻塞在等待结果的线程上。
var text=downloadSync('http://example.com/file.txt',function(text){
console.log(text);
});
该API初始化下载进行,然后在内部注册表中存储了回调函数后立即返回,而不是被网络请求阻塞。当下载完成之后,系统会将下载完的文件的文本作为参数调用该已注册的回调函数。
随着事件的发生,事件被添加到应用程序的事件队列的末尾。js系统使用一个内部循环机制来执行应用程序。该循环机制每次都拉取队列底部的事件,以接收到这些事件的顺序来调用这些已经注册的js事件处理程序,并将事件的数据作为该事件处理程序的参数。
运行到完成机制担保的好处是当代码运行时,你完全掌握应用程序的状态。根本不必担心一些变量和对象属性的改变由于并发执行代码而超出你的控制。并发编程在js中往往比使用线程和锁的c++,java或c#更容易。
然而,运行到完成机制的不足是,实际上所有你编写的代码支撑着余下应用程序的继续执行。像浏览器这样的交互式应用程序中,一个阻塞的事件处理程序会阻塞任何将被处理的其他用户输入,甚至可能阻塞一个页面的渲染,从而导致页面失去响应的用户体验。在服务器环境中,一个阻塞的事件处理程序可能会阻塞将被处理的其他网络请求,从而导致服务器失去响应。
js并发的一个最重要的规则是绝不要在应用程序事件队列中使用阻塞I/O的API。在浏览器中,甚至几乎没有任何阻塞API是可用的,尽管有一些平台实现了。提供类似于downloadAsync功能的网络I/O的XMLHttpRequest库有一个同步的版本实现,被认为是不好的。对于web应用程序的交互性,同步的I/O会导致灾难性的后果,它在I/O操作完成之前一直会阻塞用户与页面的交互。
相比之下,异步的API用在基于事件的环境中是安全的,它们迫使应用程序逻辑在一个独立的事件循环“轮询”中继续处理。如上面的例子,假设需要几秒钟来下载网络资源,在这段时间里,数量庞大的其他事件很可能发生。在同步的实现中,这些事件就会堆积在事件队列中,而事件循环将停留等待该JS代码执行完成,这将阻塞任何其他事件的处理。在异步的版本中,JS代码注册一个事件处理程序并立即返回,这将在下载完成之前,允许其他处理程序处理这期间的事件。
在主应用程序事件队列不受影响的环境中,阻塞操作很少出问题。例如,web平台提供了Worker的API,该API使得产生大量的并行计算成为可能。不同于传统的线程执行,Workers在一个完全隔离的状态下执行,没有获取全局作用域或应用程序主线程web页面内容的能力。因此,它们不会妨碍主事件队列中运行的代码的执行。在一个Worker中,使用XMLHttpRequest同步的变种很少出问题。下载操作的确会阻塞Worker继续执行,但这并不会阻止页面的渲染或事件队列中的事件响应。在服务器端环境中,阻塞的API在启动一开始是没有问题的,也就是在服务器开始响应输入的请求之前。然后在处理请求期间,浏览器事件队列中存在阻塞的API就是有问题的啦。
提示
异步API使用回调函数来延缓处理代价高昂的操作以避免阻塞主应用程序
js并发地接收事件,但会使用一个事件队列按序地处理事件处理程序
在应用程序事件队列中绝不要使用阻塞的I/O
[Effective JavaScript 笔记]第61条:不要阻塞I/O事件队列的更多相关文章
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记]第65条:不要在计算时阻塞事件队列
第61条解释了异步API怎样帮助我们防止一段程序阻塞应用程序的事件队列.使用下面代码,可以很容易使一个应用程序陷入泥潭. while(true){} 而且它并不需要一个无限循环来写一个缓慢的程序.代码 ...
- [Effective JavaScript 笔记]第62条:在异步序列中使用嵌套或命名的回调函数
异步程序的操作顺序 61条讲述了异步API如何执行潜在的代价高昂的I/O操作,而不阻塞应用程序继续处理其他输入.理解异步程序的操作顺序刚开始有点混乱.例如,下面的代码会在打印"finishe ...
- [Effective JavaScript 笔记]第67条:绝不要同步地调用异步的回调函数
设想有downloadAsync函数的一种变种,它持有一个缓存(实现为一个Dict)来避免多次下载同一个文件.在文件已经被缓存的情况下,立即调用回调函数是最优选择. var cache=new Dic ...
- [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑
构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...
- [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合
对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...
随机推荐
- Orchard使用Tags(标签)组织文本
本文链接:http://www.cnblogs.com/souther/p/4517476.html 主目录 原文链接:http://docs.orchardproject.net/Documenta ...
- Android学习第六弹之Touch事件的处理
在移动开发过程当中,我们经常会遇到手势处理和事件触摸的情况,如果不了解整个事件的处理机制,对于开发的同学和码农是非常痛苦的,但是事件触摸的处理确实是一个非常复杂的过程,细讲起来,估计我都能讲迷糊,这里 ...
- AngularJS——grunt神器的安装
前言: 刚开始学 angularJS,在慕课网上看的大漠老师的视频(http://www.imooc.com/learn/156),里面刚开始讲述了前端开发-调试-测试所使用的手段和工具,本人对前端开 ...
- ECMAScript —— 学习笔记(思维导图版)
导图
- Web Service 小练习
对于网站与网站之间数据互动,这是我的说法,不是专家说的,不要相信.应该有专业的说法. 从他人的网站通过一个接口获取数据,这一直是我感到神奇的事,怎么实现的,一直萦绕于心,想要弄过究竟,怎么是实现的啊! ...
- 每天一个linux命令(15):whereis 命令
whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b).man说明文件(参数-m)和源代码文件(参数-s).如果省略参数,则返回所有信息. 和 find相比,whereis查找的速度 ...
- Linux operation strucutre
Under the /usr/src directory. 1.arch目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CP ...
- 【CodeForces 557B】Pasha and Tea
题 题意 总共有 w 克蛋糕,2n 个盘子,第 i 个盘子容量为 ai ,n 个女孩和 n 个男孩,男孩得到的是女孩得到的蛋糕的两倍,求他们得到蛋糕的最大值. 分析 把盘子从小到大排序,然后 女生得到 ...
- BZOJ-1975 魔法猪学院 K短路 (A*+SPFA)
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1323 Solved: 433 [Submit][Statu ...
- 网络包处理工具NetBee
What is NetBee? NetBee is a new library intended for several types of packet processing, such as pac ...