[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循环,先输出哪个属性都有可能.获取和设置 ...
随机推荐
- SQL替换语句之批量修改、增加、删除字段内容
语法 REPLACE ( original-string, search-string, replace-string ) 用法 update 表的名称 set 替换字段=REPLACE(替换字段,原 ...
- android之显示数据库信息
关键字 ListView adapter MVC 在android开发中也使用到了MVC架构,其中的xml布局文件就是V,M就是我们定义好的javabean类,而控制器就是就是适配器类adapter ...
- C#基础知识系列一(goto、i++、三元运算符、ref和out、String和string、重载运算符)
前言 这两天在网上看到的总结很多,尤其是博客园中的,很多很多,也给了我很多的启发,当然自己也总结过,而且有很多人也给与我一些意见和看法.不管怎样,自己还是先把所谓的基础知识加强巩固下吧. 2014年的 ...
- 无法加载协定为“ServiceReference1.xxxxx”的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分
原因是config节点中有多个endpoint相同节点,提示按名称指示首选的终结点,说明程序不知道选那个节点. 解决办法,实例化service服务对象时,通过name值指定创建它. config文件部 ...
- 使用 ArcGIS中的ArcObjects进行二次开发
参考网址:https://blogs.esri.com/esri/arcgis/2012/12/07/arcobjects-or-runtime-sdk/ http://resources.arcgi ...
- OC基础--OC中类的定义
OC中类的定义与使用跟C#和java差别相当明显,做个笔记,牢记并加以区别! 一.OC中类的定义:关键字@implementation 和 @end 注意事项: 1.定义好一个类之后,要让这个类继承N ...
- HP 电脑装 纯净版的win7
新买的 HP 电脑,自带 Win10 的操作系统,今天把它改成 装win7 系统 在安装的过程中遇到的问题 1.数字证书错误.您安装的操作系统来源不明之类的错误,具体没有记下来 2.磁盘的格式不是NT ...
- 转:浅谈CSS在前端优化中一些值得注意的关键点
前端优化工作中要考虑的元素多种多样,而合理地使用CSS脚本可以在很大程度上优化页面的加载性能,以下我们就来浅谈CSS在前端优化中一些值得注意的关键点: 当谈到Web的“高性能”时,很多人想到的是页面加 ...
- Windows python3.3下安装BeautifulSoup
首先在官网下载:http://www.crummy.com/software/BeautifulSoup/#Download BeautifulSoup在版本4以上都开始支持python3了,所以就下 ...
- Linux Kernel中获取当前目录方法(undone)
目录 . 引言 . 基于进程内存镜像信息struct mm_struct获取struct path调用d_path()获取当前进程的"绝对路径" . 基于文件描述符(fd).tas ...