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

Node.js是一个异步非阻塞I/O的JavaScript运行环境。在Node.js中非阻塞I/O是其最主要的特征。异步、事件驱动、非阻塞I/O是Node.js存在的原因之一。理解Node.js的阻塞与非阻塞是非常重要的。

什么是阻塞与非阻塞

阻塞是指在某个操作执行过程中会阻碍后续代码的运行。非阻塞指在某个操作执行过程中不会阻碍后续代码的运行。

在I/O操作中,阻塞在读取或写入数据时会阻塞后续代码的运行,而非阻塞则不会。

阻塞I/O

Node.js中的阻塞I/O是指在执行I/O操作时,阻塞后续代码的运行。由于Node.js是单线程运行,当主线程遇到阻塞I/O操作时,它将会停滞在那里等待I/O操作执行完成返回,阻塞了代码的执行和服务器的响应。

下面是一个阻塞I/O的例子:

const fs = require('fs');
// 在执行完读文件的操作之后会继续执行后面的代码
const data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log('程序执行结束');

fs.readFileSync()是Node.js的同步I/O函数,它会阻塞代码的执行并等待文件读取完毕返回数据后再执行后面的代码。因此在读取文件的过程中,程序被阻塞住,直到文件读取完毕并返回数据后才会输出数据和"程序执行结束"。

非阻塞I/O

Node.js中的非阻塞I/O是指在执行I/O操作时,不会阻塞后续代码的运行。Node.js通过事件循环机制实现非阻塞I/O。

下面是一个非阻塞I/O的例子:

const fs = require('fs');
fs.readFile('input.txt', function (err, data) {
    if (err) {
        return console.error(err);
    }
    console.log(data.toString());
});
console.log('程序执行结束');

fs.readFile()是Node.js的异步I/O函数,它会将I/O操作加入到事件队列中,继续执行后续代码,等待I/O事件完成后会被扔到事件循环机制中执行回调函数。因此在读取文件的过程中,程序会继续执行后续代码,输出"程序执行结束",直到文件读取完毕后才会输出文件数据。

阻塞I/O与非阻塞I/O的对比

阻塞I/O会在I/O操作完成前阻碍后续代码的执行,而非阻塞I/O不会阻碍后续代码的执行,因此非阻塞I/O对于I/O密集型的场景非常有用。

Node.js采用一种事件循环的机制来处理I/O请求。在事件循环的每一个循环次数中,Node.js都会从事件队列中取出并处理一个事件。如果事件处理函数中触发了I/O请求,那么程序会将请求交给操作系统并继续往后执行,直到I/O操作完成并触发相应的回调函数。

Node.js中通过回调函数的方式解决了阻塞I/O带来的性能问题,使得Node.js在I/O密集型的场景中有非常优异的表现。

示例说明

示例1:文件夹遍历

下面是一个使用Node.js来遍历指定文件夹的例子,使用阻塞和非阻塞的方式分别实现:

  • 阻塞方式
const fs = require('fs');

function getFileList(path) {
    const fileArr = [];
    const fileList = fs.readdirSync(path);
    fileList.forEach(function(file) {
        fileArr.push(file);
    });
    return fileArr;
}

const list = getFileList('./');
console.log(list);
  • 非阻塞方式
const fs = require('fs');

function getFileList(path) {
    const fileArr = [];
    fs.readdir(path, function(err, fileList) {
        fileList.forEach(function(file) {
            fileArr.push(file);
        });
        console.log(fileArr);
    });
}

getFileList('./');

示例2:HTTP服务器

下面是一个使用Node.js实现的简单的HTTP服务器,使用阻塞和非阻塞的方式分别实现:

  • 阻塞方式
const http = require('http');
const fs = require('fs');

http.createServer(function (req, res) {
    const data = fs.readFileSync('index.html');
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(data);
}).listen(8080);
console.log('服务器启动成功!请在浏览器中访问 http://localhost:8080');
  • 非阻塞方式
const http = require('http');
const fs = require('fs');

http.createServer(function (req, res) {
    fs.readFile('index.html', function(err, data) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(data);
    });
}).listen(8080);
console.log('服务器启动成功!请在浏览器中访问 http://localhost:8080');

在执行这个简单的HTTP服务器时,使用非阻塞方式的服务器在文件读取的同时可以继续响应客户端请求,而使用阻塞方式的服务器必须等待文件读取完成后才能响应客户端请求,性能明显落后。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Node.js 阻塞与非阻塞的实现 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • 深入探讨javascript函数式编程

    深入探讨Javascript函数式编程 Javascript 函数式编程是一种将函数作为主要构建块的编程范式。与传统的命令式编程不同,函数式编程通过组合函数来完成任务,这使得代码更加简洁、模块化和易于测试。本篇文章将深入探讨Javascript函数式编程的一些关键概念以及如何在实践中应用它们。 函数式编程的核心概念 纯函数 Javascript 中的纯函数是…

    node js 2023年6月8日
    00
  • 浅谈开发eslint规则

    下面是“浅谈开发eslint规则”的完整攻略,主要包括以下部分: 1. 简介 ESLint是一个用于检查JavaScript代码是否符合规范的工具,它提供了一系列的规则(Rules),可以帮助开发者统一代码风格、提高代码质量、减少代码缺陷等。但是,ESLint规则并不能覆盖所有的情况,有些特定的代码规范需要开发者自己开发,这就需要使用到自定义规则(Custo…

    node js 2023年6月8日
    00
  • 使用nodeJS中的fs模块对文件及目录进行读写,删除,追加,等操作详解

    使用fs模块进行文件及目录的读写、删除、追加等操作 在Node.js中,fs模块是负责文件系统操作的模块。它提供了丰富的API接口,可以实现对文件及目录进行读写、删除、追加等操作。下面我们详细讲解如何使用fs模块进行这些操作。 读取文件 读取文件最简单的方式是使用fs.readFile方法,该方法接受两个参数:文件路径和回调函数。回调函数的第一个参数是读取到…

    node js 2023年6月8日
    00
  • Node对CommonJS的模块规范

    Node.js是一种基于Chrome V8引擎的JavaScript运行时环境,可以直接在命令行中运行JS文件,同时也支持运行Web服务器等后端应用。在Node.js中,模块化是一个非常重要的特性,Node采用CommonJS规范来实现模块化。 CommonJS规范 CommonJS规范定义了模块的基本概念、模块的引入和导出机制,以及模块的缓存等内容。在Co…

    node js 2023年6月8日
    00
  • 详解nodejs 文本操作模块-fs模块(三)

    针对“详解nodejs 文本操作模块-fs模块(三)”这篇文章,以下是该文的完整攻略: 详解nodejs 文本操作模块-fs模块(三) 概述 本文将详细介绍 nodejs 中文件读写模块 fs 的相关操作,包括: 文件读写基础 API 同步和异步操作模式 文件创建、删除和重命名 文件状态查询等 文件读写基础 API fs 模块提供了多个文件读写的基础 API…

    node js 2023年6月8日
    00
  • 浅析node命令行交互原理

    浅析node命令行交互原理 简介 在日常工作中,我们可能需要通过命令行与node.js程序进行交互来完成一些任务。本文将会深入浅出地讲解node命令行交互的原理及相关示例。 node命令行交互原理 node.js的命令行交互主要是基于node.js的标准库 readline 模块实现的。readline 模块提供了一组接口,可以创建一个读取命令行输入流的实例…

    node js 2023年6月8日
    00
  • 重学 JS:为啥 await 不能用在 forEach 中详解

    当我们使用 async/await 来处理异步函数时,有可能会遇到在 forEach 循环中使用 await 语句,导致 await 处理不完整的问题,这是因为 forEach 循环的特殊性导致的。 问题 forEach 循环是 JavaScript 提供的一种遍历数组的方式,常用于对数组中的每一项进行操作,语法如下: array.forEach(callb…

    node js 2023年6月8日
    00
  • TypeScript安装与使用的详细教程

    下面是TypeScript安装与使用的详细教程: 安装 1. 安装node.js 首先,我们需要安装node.js,可以使用node.js官网提供的安装包进行安装。 2. 安装TypeScript node.js安装完成后,我们可以使用npm命令安装TypeScript。在命令行工具中执行以下命令: npm install -g typescript 这样就…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部