到底什么是壅闭(Blocking)与非壅闭(Non-Blocking)?

访客4年前黑客文章937

这篇博客将先容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中 *** 代码执行是单线程的,因此并发指的是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监控。

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



思源资源网:分类流动

1.阿里云: 本站现在使用的是阿里云主机,平安/可靠/稳固。点击领取2000米代金券、领会最新阿里云产物的种种优惠流动点击进入

相关文章

司机开车时边撸狗边看书怎么回事 详细经过现场图网友炸了

司机开车时边撸狗边看书怎么回事 详细经过现场图网友炸了

【司机开车时边撸狗边看书】近日,吉林长春市民高先生驾车行驶在高架桥上,目睹一只宠物狗从前方车辆主驾驶位窗户处探出。高先生驱车凑近,没想到该车车主方向盘处放置一本书正在阅读!他表示,看到对方一边看书一边...

苹果汁的功效与作用(苹果汁可以止泻吗)

  秋冬季是拉肚子病的多发时节,由于高温天气,病菌的繁育速率迅速,经常会造成消化道层面的病症。如结肠炎、细菌性痢疾、伤寒论这些。这种胃肠道疾病临床症状的一个相同点便是拉肚子。腹泻是种常见症状,就是指大...

卖什么东西最好卖?每一个成功的人都有一个开始

伴随着社会发展的发展,时期不断创新,大家生活水平持续改进,喜爱价廉物美的物品依然是我们中国人的消费习惯,近期很多人问如今卖什么最好是卖?在这儿我想说,如果你留意观查,实际上有很多做生意都值得去做,并且...

别克君越换机油多少钱,君越更换机油多少钱

  别克2016君越1.5t换一次机油要几多钱?并且我的车是新车才跑了2500多公里。   一般来说一次通例的调养差不多在400到500元阁下,是较量公道的。这个,剩余38%应该不是指的是机油的剩余量...

新生儿补钙吃什么牌子(宝宝鱼肝油牌子排行榜)

钙是婴儿成长全过程中不可或缺的矿物之一,新生儿期是婴儿成长最重要的阶段。由于宝宝看起来迅速,因此 必须大量的钙。依据剖析,新生婴儿身体的钙约占休重的2%。因为钙是身体的关键原素之一,如何给宝宝填补钙对...

Dedecms某一处insert型注入

Dedecms某一处insert型注入

Dedecms一处注入,较鸡肋,之前变量覆盖的漏洞太轰动了,所以一直没发出,之前5月份最新版本测试的,目前最新版本应该是没修复的 漏洞需要会员,所以比较鸡肋啦! 发表文章处,post表单的mtypes...