Node.js 阻塞与非阻塞的实现

 更新时间:2023年05月24日 09:28:29   作者:和你一起去月球  
本文主要介绍了Node.js中阻塞和非阻塞调用之间的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1、简介

本概述介绍了Node.js中阻塞和非阻塞调用之间的区别。本概述将参考事件循环和libuv,但不需要事先了解这些主题。假设读者对JavaScript语言和Node.js回调模式有基本的理解。

“I/O”主要指与libuv支持的系统磁盘和网络的交互。

2、阻塞

阻塞是指Node.js进程中额外JavaScript的执行必须等待非JavaScript操作完成。发生这种情况是因为在发生阻塞操作时,事件循环无法继续运行JavaScript。

在Node.js中,由于CPU密集型,而不是等待非JavaScript操作(如I/O),而表现出较差性能的JavaScript通常不被称为阻塞。Node.js标准库中使用libuv的同步方法是最常用的阻塞操作。原生模块也可能具有阻塞方法。

Node.js标准库中的所有I/O方法都提供非阻塞的异步版本,并接受回调函数。有些方法也有阻塞的对应方法,它们的名称以Sync结尾。

3、对比代码

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

以文件系统模块为例,这是一个同步文件读取:

const fs = require('fs');
const data = fs.readFileSync('/file.md'); // blocks here until file is read

一个异步示例:

const fs = require('fs'); 
fs.readFile('/file.md', (err, data) => { 
      if (err) throw err; 
});

第一个例子看起来比第二个简单,但缺点是第二行会阻止任何附加JavaScript的执行,直到整个文件被读取。请注意,在同步版本中,如果抛出错误,则需要捕获错误,否则进程将崩溃。在异步版本中,由作者决定是否应该抛出错误。

我们稍微扩展一下我们的示例:

const fs = require('fs');
const data = fs.readFileSync('/file.md'); // blocks here until file is read
console.log(data);
moreWork(); // will run after console.log

一个类似但不等价的异步示例:

const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
  if (err) throw err;
  console.log(data);
});
moreWork(); // will run before console.log

在上面的第一个例子中,console.log将在moreWork()之前调用。在第二个例子中,fs.readFile()是非阻塞的,因此JavaScript可以继续执行,并将首先调用moreWork()。在不等待文件读取完成的情况下运行moreWork()的能力是实现更高吞吐量的关键设计选择。

4、并发性和吞吐量

Node.js中的JavaScript执行是单线程的,因此并发是指事件循环在完成其他工作后执行JavaScript回调函数的能力。任何期望以并发方式运行的代码都必须允许事件循环在非JavaScript操作(如I/O)发生时继续运行。

作为一个例子,让我们考虑这样一种情况,即对web服务器的每个请求需要50毫秒才能完成,其中45毫秒是可以异步完成的数据库I/O。选择非阻塞异步操作可以为每个请求释放45ms的时间来处理其他请求。仅仅通过选择使用非阻塞方法而不是阻塞方法,这在容量上是一个显著的差异。

事件循环不同于许多其他语言中的模型,在这些语言中可以创建额外的线程来处理并发工作。

5、混合阻塞和非阻塞代码

在处理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.readFile()的回调中放置了对fs.unlink()的非阻塞调用,这保证了操作的正确顺序。

到此这篇关于Node.js 阻塞与非阻塞的实现的文章就介绍到这了,更多相关Node 阻塞与非阻塞内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Node.js实现ORM的一种思路详解(图文)

    使用Node.js实现ORM的一种思路详解(图文)

    这篇文章主要介绍了用Node.js实现ORM的一种思路详解(图文),需要的朋友可以参考下
    2017-10-10
  • 在Debian(Raspberry Pi)树莓派上安装NodeJS的教程详解

    在Debian(Raspberry Pi)树莓派上安装NodeJS的教程详解

    在树莓派上运行NodeJS并不需要特别的配置,你只需要确保可以用openssh远程连接到你的树莓派就ok了,关于在Debian(Raspberry Pi)树莓派上安装NodeJS的方法,大家可以通过本文了解下
    2017-09-09
  • NodeJS收发GET和POST请求的示例代码

    NodeJS收发GET和POST请求的示例代码

    本篇文章主要介绍了NodeJS收发GET和POST请求的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Linux下为Node.js程序配置MySQL或Oracle数据库的方法

    Linux下为Node.js程序配置MySQL或Oracle数据库的方法

    这篇文章主要介绍了Linux下为Node.js程序配置MySQL或Oracle数据库的方法,这里默认已经装配好了Node环境然后我们利用npm包管理工具来进行配置,需要的朋友可以参考下
    2016-03-03
  • node.js微信公众平台开发教程

    node.js微信公众平台开发教程

    这篇文章主要为大家分享了node.js微信公众平台开发教程,如何进行微信开发,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • 发布一款npm包帮助理解npm的使用

    发布一款npm包帮助理解npm的使用

    这篇文章主要介绍了发布一款npm包帮助理解npm的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Nodejs中的JWT和Session的使用

    Nodejs中的JWT和Session的使用

    这篇文章主要介绍了Nodejs中的JWT和Session的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • 轻松创建nodejs服务器(2):nodejs服务器的构成分析

    轻松创建nodejs服务器(2):nodejs服务器的构成分析

    这篇文章主要介绍了轻松创建nodejs服务器(2):nodejs服务器的构成分析,本文是对第一节中简单服务器的代码进行分析总结,需要的朋友可以参考下
    2014-12-12
  • Node.js环境下JavaScript实现单链表与双链表结构

    Node.js环境下JavaScript实现单链表与双链表结构

    Node环境下通过npm可以获取list的几个相关库,但是我们这里注重于自己动手实现,接下来就一起来看一下Node.js环境下JavaScript实现单链表与双链表结构
    2016-06-06
  • 搭建pomelo 开发环境

    搭建pomelo 开发环境

    Pomelo是基于 Node.js 的高性能、分布式游戏服务器框架。它包括基础的开发框架和相关的扩展组件(库和工具包),可以帮助你省去游戏开发枯燥中的重复劳动和底层逻辑的开发。Pomelo不但适用于游戏服务器开发,也可用于开发高实时 Web 应用
    2014-06-06

最新评论