译者按: Node.js文档阅读系列之一。

  • 原文: Overview of Blocking vs Non-Blocking
  • 译者: Fundebug

为了保证可读性,本文采用意译而非直译。

这篇博客将介绍Node.js的阻塞(Blocking)与非阻塞(Non-Blocking)。我会提到Event Loop与libuv,但是不了解它们也不会影响阅读。读者只需要有一定的JavaScript基础,理解Node.js的回调函数(callback pattern)就可以了。

博客中提到了很多次I/O,它主要指的是使用libuv与系统的磁盘与网络进行交互。

阻塞(Blocking)

阻塞指的是一部分Node.js代码需要等到一些非Node.js代码执行完成之后才能继续执行。这是因为当阻塞发生时,Event Loop无法继续执行。

对于Node.js来说,由于CPU密集的操作导致代码性能很差时,不能称为阻塞。当需要等待非Node.js代码执行时,才能称为阻塞。Node.js中依赖于libuv的同步方法(以Sync结尾)导致阻塞,是最常见的情况。当然,一些不依赖于libuv的原生Node.js方法有些也能导致阻塞。

Node.js中所有与I/O相关的方法都提供了异步版本,它们是非阻塞的,可以指定回调函数,例如fs.readFile。其中一些方法也有对应的阻塞版本,它们的函数名以Sync结尾,例如fs.readFileSync。

代码示例

阻塞的方法是同步执行的,而非阻塞的方法是异步执行。

以读文件为例,下面是同步执行的代码:

const fs = require('fs');
const data = fs.readFileSync('/file.md'); // 文件读取完成之前,代码会阻塞,不会执行后面的代码
console.log("Hello, Fundebug!"); // 文件读取完成之后才会打印
复制代码

对应的异步代码如下:

const fs = require('fs');
fs.readFile('/file.md', (err, data) => {if (err) throw err;
}); // 代码不会因为读文件阻塞,会继续执行后面的代码
console.log("Hello, Fundebug!"); // 文件读完之前就会打印
复制代码

第一个示例代码看起来要简单很多,但是它的缺点是会阻塞代码执行,后面的代码需要等到整个文件读取完成之后才能继续执行。

在同步代码中,如果读取文件出错了,则错误需要使用try...catch处理,否则进程会崩溃。对于异步代码,是否处理回调函数的错误则取决于开发者。

我们可以将示例代码稍微修改一下,下面是同步代码:

const fs = require('fs');
const data = fs.readFileSync('/file.md');
console.log(data);
moreWork(); // console.log之后再执行
复制代码

异步代码如下:

const fs = require('fs');
fs.readFile('/file.md', (err, data) => {if (err) throw err;console.log(data);
});
moreWork(); // 先于console.log执行
复制代码

在第一个示例中,console.log将会先于moreWork()执行。在第二个示例中,由于fs.readFile()是非阻塞的,代码可以继续执行,因此moreWork()会先于console.log执行。

moreWork()不用等待读取整个文件,可以继续执行,这是Node.js可以增加吞吐量的关键。

并发与吞吐量

Node.js中JS代码执行是单线程的,因此并发指的是Event Loop可以在执行其他代码之后再去执行回调函数。如果希望代码可以并发执行,则所有非JavaScript代码比如I/O执行时,必须保证Event Loop继续运行。

举个例子,假设Web服务器的每个请求需要50ms完成,其中45ms是数据库的I/O操作。如果使用非阻塞的异步方式执行数据库I/O的话,则可以节省45ms来处理其他请求,这可以极大地提高系统的吞吐量。

Event Loop这种方式与其他许多语言都不一样,通常它们会创建新的线程来处理并发。

混用阻塞与非阻塞代码会出问题

当我们处理I/O时,应该避免以下代码:

const fs = require('fs');
fs.readFile('/file.md', (err, data) => {if (err) throw err;console.log(data);
});
fs.unlinkSync('/file.md');
复制代码

上面的示例中,fs.unlinkSync()很可能在fs.readFile()之前执行,也就是说,我们在读取file.md之前,这个文件就已经被删掉了。

为了避免这种情况,我们应该是要非阻塞方式,来保证它们按照正确的顺序执行。

const fs = require('fs');
fs.readFile('/file.md', (readFileErr, data) => {if (readFileErr) throw readFileErr;console.log(data);fs.unlink('/file.md', (unlinkErr) => {if (unlinkErr) throw unlinkErr;});
});
复制代码

上面的示例中,我们把非阻塞的fs.unlink()放在fs.readFile()的回调函数中。

参考

  • libuv
  • About Node.js

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业。欢迎大家免费试用!

版权声明

转载时请注明作者Fundebug以及本文地址: blog.fundebug.com/2019/06/12/…

转载于:https://juejin.im/post/5d005914f265da1bc8542112

Node.js官方文档:到底什么是阻塞(Blocking)与非阻塞(Non-Blocking)?相关推荐

  1. Node.js 官方文档中文版

    这目录也是醉了 . 列出跟没列出没两样 转载于:https://www.cnblogs.com/ganmk--jy/p/5646860.html

  2. GO.js官方文档中文版

    GoJs是一个实现图表交互的javaScript库,这篇文章将为你展示使用GoJs时的特征.因为GoJs是依赖hTML5的javaScript库,所以你要确认你开发的页面是在HTML技术的基础上,当然 ...

  3. quill.js官方文档(六)【增量Delta】

    Delta被用做描述Quill编辑器的内容和变化,简单但表达力强的数据格式.这种格式本质上是一种JSON格式,人类可读同时及其也能容易识别.Delta能描述任意Quill内容,包括所有的文本.格式信息 ...

  4. vue.js官方文档 PDF

    链接:https://pan.baidu.com/s/1jHMBb5W 密码:gsks 如果失效,留下邮箱给你发过去 转载于:https://www.cnblogs.com/zlfProgrammer ...

  5. 基于vue的微信小程序开发5分钟上手教程(官方文档转)

    使用手册 mpvue 继承自 Vue.js,其技术规范和语法特点与 Vue.js 保持一致. 注:其实就是官方文档,只是习惯看博文学习才直接copy过来的,详见官方文档 本文档适用于有一定 Vue.j ...

  6. 都在夸官方文档 Vue.js 2021 年度报告出炉!

    整理 | 苏宓 出品 | CSDN(ID:CSDNnews) 作为前端开发框架三剑客之一,Vue 自 2014 年发布以来,成为很多开发者必备的工具. 近日,国外软件开发机构 Monterail 在对 ...

  7. vue.js 2.0 官方文档学习笔记 —— 01. vue 介绍

    这是我的vue.js 2.0的学习笔记,采取了将官方文档中的代码集中到一个文件的形式.目的是保存下来,方便自己查阅. !官方文档:https://cn.vuejs.org/v2/guide/ 01. ...

  8. Sencha Cmd 6 和 Ext JS 6 指南文档(部分官方文档中文翻译)

    近期组织了几个程序员网友,正在翻译一部分官方的Sencha Cmd 6 和 Ext JS 6 指南文档. 眼下还没翻译完,大家能够先看看 Sencha Cmd 6 和 Ext JS 6 指南文档  ( ...

  9. mysql 标识符规则_MySQL 标识符到底区分大小写么——官方文档告诉你

    最近在阿里云服务器上部署一个自己写的小 demo 时遇到一点问题,查看 Tomcat 日志后定位到问题出现在与数据库服务器交互的地方,执行 SQL 语句时会返回 指定列.指定名 不存在的错误.多方查证 ...

最新文章

  1. 图像零交叉点,视频生成,视频识别,视频摘要,视频浓缩
  2. micropython 实时音频传输_在线实时合唱的实现原理与难点是什么?
  3. php+数组转换函数是,php数组与字符串的转换函数大全
  4. ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER
  5. 互联网企业安全之端口监控
  6. CentOS Linux解决Device eth0 does not seem to be present【转】
  7. JavaScript学习(六十四)—关于JS的浮点数计算精度问题解决方案
  8. pandas数据处理实践二(排序(sort_index()、sort_values())、连接(Concatenate(连接,串联)和Combine(结合、联合))
  9. pythonclass使用教程_【Python 1-15】Python手把手教程之——详解类Class以及类的使用...
  10. 分布式文件存储FastDFS之配置Nginx模块
  11. Redis常用命令总结,为什么阿里的程序员成长如此之快
  12. 谷粒商城笔记 + 完整代码 + 课件资料(基础篇)(学习记录)
  13. 计算机审计风险背景,计算机审计风险探究
  14. android ios相机,曝苹果iOS13相机加入了这项功能 安卓上早就有了
  15. Activiti工作流会签一 部署流程
  16. 阿诺德·施瓦辛格的演讲(拼命才会优秀,自律才会自由~)
  17. 国内VR体验馆发展现状及未来前景
  18. Casbin入选2022 Google编程之夏
  19. kindeditor默认粘贴为无文本格式怎么实现配置
  20. 服务器基础设置:H3C服务器,ilo地址,管理员密码、PXE启动、虚拟化是否打开

热门文章

  1. 五月集训——Day4:1400
  2. {“msg“:“success“,“code“:0,“data“:[]}
  3. 关于使用Java后台导入excel文件,读取数据后,更新数据库,并返回数据给到前端的相关问题总结
  4. Java毕业设计_ 校园志愿者服务管理平台
  5. 实训 Day09 实习日志
  6. 计算机图形学——二维图形变换裁剪
  7. 要写易删除,而不易扩展的代码
  8. ubuntu 麦克风录音_Ubuntu 20.04 开启隐藏录音降噪功能(推荐)
  9. 用科技词汇润色下句:并将模型在中国西北地区应用,对水碳能耦合循环过程进行定量评估和时空格局分析,旨在优化区域生态系统管理策略。...
  10. 使用Docker部署GitLab、Nexus、Registry私服