阿八博客
  • 100000+

    文章

  • 23

    评论

  • 20

    友链

  • 最近新加了很多技术文章,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

[书籍翻译] 《JavaScript并发编程》第一章 JavaScript并发简介

欢迎来到阿八个人博客网站。本 阿八个人博客 网站提供最新的站长新闻,各种互联网资讯。 喜欢本站的朋友可以收藏本站,或者加QQ:我们大家一起来交流技术! URL链接:https://www.abboke.com/jsh/2019/1010/116438.html
本文是我翻译《JavaScript Concurrency》书籍的第一章,该书主要以Promises、Generator、Web workers等技术来讲解JavaScript并发编程方面的实践
完整书籍翻译地址:https://github.com/yzsunlei/j...
由于能力有限,肯定存在翻译不清楚甚至翻译错误的地方,欢迎朋友们提issue指出,感谢

JavaScript并不是一门与并发有关联的语言
事实上,它的特性还与并发应用是完全不相符的
近几年来,它已经改变了很多,特别是ES2015新的语言特性
Promises已经在JavaScript中运用了好几年了; 只是现在,它成为JavaScript语言的
一种原生类型

Generators是JavaScript的另一个特性,它改变了我们对JavaScript语言中并发的思考方式
Web workers也已经被浏览器支持好几年了,然而,我们却运用的并不多
也许,是因为它与并发关系不大,而且更多的原因是它在我们的应用程序中关于并发扮演的角色的理解

本章的目标是探讨一些通用的并发思想,从并发是什么开始讲起
如果您在工作或学习中没有任何的并发编程经验,那很好,本章对您来说是一个很不错的起点
如果您以前使用JavaScript或其他语言完成过并发编程相关的项目,那可以将本章作为复习,并使用JavaScript来回顾下

我们将以一些重要的并发原则来贯穿本章
这些原则是有价值的编程工具,我们应该在编写并发代码时牢记在脑海中
一旦我们学会应用这些原则,它们会告诉我们我们的并发设计是否正确,或者需要退后一步,问问自己真正想要实现的目标
这些原则采用自上而下的方法来设计我们的应用程序
这意味着它们从一开始就是适用的,甚至在我们开始编写代码之前
在整本书中,我们将引用这些原则,因此如果您只阅读本章的一节,那最好是并发原则那部分

同步JavaScript

在我们开始构建大规模并发JavaScript体系结构之前,让我们先将注意力转移到我们熟悉的、老旧的同步JavaScript代码上
这些JavaScript代码块,它们作为单击事件的回调结果,或者作为加载网页的运行结果
一旦它们开始执行,它们就不会停止
也就是说,它们是一直运行到完成的
在接下来的章节中,我们将进一步深入研究它们

我们在整个章节中偶尔会看到术语“同步”和“串行”,它们可互换使用
它们都是指代一个接一个地运行代码语句,直到没有其他代码可以运行

尽管JavaScript被设计为单线程,运行直到完成的,但Web的特性不得不使其复杂化
想想Web浏览器及其所有可应用的模块
有用于渲染用户界面的文档对象模型(DOM),有用于获取远程数据的XMLHttpRequest(XHR)对象
现在让我们先来看看JavaScript的同步特性和Web的异步特性

同步是很容易理解的

当代码是同步的,它很容易被理解
将我们在屏幕上看到的指令集映射到头脑中的有序步骤相当容易; 这样做,然后那样做;判断一下,如果是,则执行此操作,依此类推
这种串行类型的代码处理很容易理解,因为没有什么特别的,假想代码的运行并不可怕
以下是一大块同步代码的示例:

在传统的多线程编程环境中,线程与线程之间是异步运行
我们使用多线程来充分利用当今大多数系统中的多核CPU,从而获得更好的性能
但是,这需要付出一些代价的,因为它迫使我们去重新思考代码在运行时的执行方式
它不再是通常的一步一步的去执行
一段代码可以与另一个CPU中的其他代码一起运行,也可以在同一CPU上与其他线程一起运行

当我们将并发引入同步代码时,很多简易性就消失了 - 它就会是很烧脑的代码
这就是我们编写并发代码的原因:提出并发的前期假设的代码
随着本书的进展,我们将详细阐述这一概念
使用JavaScript,并发设计很重要,因为这就是Web的工作方式

异步是不可避免的

JavaScript中的并发是一个很重要的方法,原因是不管是从非常高的层次,还是实现细节水平上来说,Web是一个并发的东西
换句话说,网络是并发的,因为在任何一个时间点,都有大量的数据流过数英里的光纤,这些光纤包围着全球
它与部署到Web浏览器的应用程序本身以及后端服务器如何处理一连串的数据请求有关

异步浏览器

让我们仔细看看浏览器以及在那里发生的各种异步操作
当用户加载网页时,页面执行的第一个操作就是下载和运行页面JavaScript代码
这本身就是一个异步操作,因为我们的代码在下载时,浏览器会继续执行其他操作,例如渲染页面元素

通过网络传输的异步数据是应用程序数据本身
加载页面并开始运行JavaScript代码后,我们需要为用户展示数据
这实际上是我们的代码将要做的第一件事,以便用户可以尽快看到
同样,当我们等待这些数据返回时,JavaScript引擎会将我们的代码移动到它的下一组指令
对远程数据的请求,在继续执行代码之前不会等待响应:

下载示例代码

您可以从http://www.packtpub.com上的帐户下载所购买的所有Packt Publishing书籍的示例代码文件

如果您在其他地方购买了本书,可以访问http://www.packtpub.com/support并注册以直接通过电子邮件发送给您

我们不仅限于获取远程数据,而是将其作为异步操作的一个案例
当我们发出网络请求时,这些异步控制流实际上会离开浏览器
但是,限制在浏览器中的异步操作呢?以setTimeout()函数为例
它遵循与网络请求使用一样的回调模式
该函数已通过回调,将在稍后执行
然而,没有任何东西离开浏览器
相反,该操作排在任何的其他操作后面
这是因为异步操作仍然只是一个控制线程,由一个CPU执行
这意味着随着我们的应用程序在规模和复杂性方面的增长,我们就会面临并发扩展问题
但是,也许异步操作并不意味着只是解决单一CPU问题

考虑在单个CPU上执行异步操作的更好方法可能是想象一下杂技师抛球的场景
杂技师的大脑比作CPU,协调他的动作
被抛出的球是我们操作的数据
我们关心的只有两个基本动作 - 抛球和接球:

不要担心这段代码运行时的机制,因为它们将在后面深入讨论
需要注意的是,当我们将一些线程放入工作环境时,我们会向已经混乱的环境添加更多回调
这就是为什么在我们的代码中需要并发设计,这是本书的主要话题,从“第5章,使用Web workers”开始

让我们考虑下前一节中杂技师的比方
抛掷和捕获动作由杂技师异步执行; 也就是说,他只有一个脑(CPU)
但是假设我们周围的环境在不断变化
我们期望的杂技动作越来越多,一个杂技师不可能全部完成:

并发

并发原则意味着利用现代CPU功能在更短的时间内计算结果
现在可以在任何现代浏览器或NodeJS环境中使用
在浏览器中,我们可以使用Web workers实现真正的并发
在NodeJS中,我们可以通过生成新进程来实现真正的并发
从浏览器的角度来看,下图这就是CPU的大致样子:

Promise的关键在于它们是一种通用的同步机制
这意味着它们不是专门针对网络请求,Web workers或DOM事件而产生的
我们必须使用promises包装我们的异步操作,并在必要时处理它们
这看起来不错的原因是依赖promise接口的调用者并不关心promise中的内容
顾名思义,Promise是在某个时刻完成的
这可能需要5秒或更快
数据可以来自网络资源或Web用户
调用者并不关心,因为它假设并发,这意味着我们可以在不破坏应用程序的情况下以任何方式实现它
这是上图的修改版本,它将为我们提供实现promises的可能性:

这种方法有两个不好的地方
首先,转换是预先进行的,这可能是一项成本高昂的计算
如果组件发生了什么问题,无法以任何方式渲染它 - 由于某种限制?然后我们执行了这个计算来转换不需要的数据
作为必然结果,我们为转换后的数据分配了一个新的数据结构,以便我们可以将它传递给我们的组件
这种瞬时存储的结构实际上并没有用于任何目的,因为它会立即被垃圾收集
让我们来看看惰性方法是什么样子的:

相关文章

暂住......别动,不想说点什么吗?
  • 全部评论(0
    还没有评论,快来抢沙发吧!