zoukankan      html  css  js  c++  java
  • Node.js 阻塞式IO与非阻塞式IO与错误处理

    2019-12-16

    13:20:53

     1.1 一个典型的 Node Web 应用程序

    大体上来说,Node 和 JavaScript 的优势之一是它们的单线程编程模型。多个线程一般会引入 bug,尽管一些新的编程语言,包括 Go 和 Rust,试图提供更加安全的并发工具,但 Node 仍然保 留了 JavaScript 在浏览器中所用的模型。在为浏览器编写代码时,我们写的指令序列一次执行一 条,代码不是并行执行的。然而对于用户界面来说,这样是不合理的:没有哪个用户想在浏览器 执行网络访问或文件获取这样的低速操作时干等着。为了解决这个问题,浏览器引入了事件机制:在你点击按钮时,就有一个事件被触发,还有一个之前定义的函数会跑起来。这种机制可以规避 一些在线程编程中经常出现的问题,比如资源死锁和竞态条件

    1.1.1 非阻塞 I/O

    那么在服务器端编程中,这有什么意义呢?其实服务器端编程面对的情况也差不多:访问磁 盘和网络这样的 I/O 请求会比较慢,所以我们希望,在读取文件或通过网络发送消息时,运行平 台不会阻塞业务逻辑的执行。Node 用三种技术来解决这个问题:事件、异步 API、非阻塞 I/O。 在 Node 程序员看来,非阻塞 I/O 是个底层术语。它的意思是说,你的程序可以在做其他事情时 发起一个请求来获取网络资源,然后当网络操作完成时,将会运行一个回调函数来处理这个操作 的结果。 图 1-1 展示了一个典型的 Node Web 应用程序,它用 Web 应用库 Express 来处理商店的订单 流程。为了购买产品,浏览器发起了一个请求,然后应用程序检查库存,为该用户创建一个账号, 发回执邮件,并返回一个 JSON HTTP 响应给浏览器。同时在做的其他事情有:发送了一封回执 邮件,更新了数据库来保存用户的详细信息和订单。代码本身很简单,就是 JavaScript 指令,但 运行平台是并发操作的,因为它用了非阻塞 I/O。

     在图 1-1 中,数据库是通过网络访问的。Node 中的网络访问是非阻塞的,它用了一个名为libuv 的库来访问操作系统的非阻塞网络调用。这个库在 Linux、macOS 和 Windows 中的实现是 不同的,但不用担心,因为你只需要会用操作数据库的 JavaScript 库就可以了。只要写一些 db.insert(query, err => {})这样的代码,Node 就会帮你完成那些经过高度优化的非阻塞 网络操作。

    访问硬盘也差不多,但又不完全一样。在生成了回执邮件并从硬盘中读取邮件模板时,libuv 借助线程池模拟出了一种使用非阻塞调用的假象。管理线程池是个苦差事,相较而言, email.send('template.ejs', (err, html) => {})这样的代码肯定要容易理解得多了。 在进行速度较慢的处理时让 Node 能做其他事情,是使用带非阻塞 I/O 的异步 API 真正的好 处。即便你只有一个单线程、单进程的 Node Web 应用,它也可以同时处理上千个网站访客发起 的连接。要想知道 Node 是如何做到的,得先研究一下事件轮询。

    1.4.2 核心模块

    Node 的核心模块就相当于其他语言的标准库,它们是编写服务器端 JavaScript 所需的工具。 大多数服务器端开发人员都知道,JavaScript 标准本身没有任何处理网络的东西,甚至连处理文 件 I/O 的东西都没有。Node 以最少的代码给它加上了文件和 TCP/IP 网络功能,使其成为了一个 可用的服务器端编程语言。 1. 文件系统 Node 不仅有文件系统库(fs、path)、TCP 客户端和服务端库(net)、HTTP 库(http 和 https) 和域名解析库(dns),还有一个经常用来写测试的断言库(assert),以及一个用来查询平台信息 的操作系统库(os)。 Node 还有一些独有库。事件模块是一个处理事件的小型库,Node 的大多数 API 都是以它为 基础来做的。比如说,流模块用事件模块提供了一个处理流数据的抽象接口。因为 Node 中的所 有数据流用的都是同样的 API,所以你可以很轻松地组装出软件组件。如果你有一个文件流读取 器,就可以很方便地把它跟压缩数据的 zlib 连接到一起,然后这个 zlib 再连接一个文件流写入器, 从而形成一个文件流处理管道。 在下面这段代码中,我们用 Node 的 fs 模块创建了读和写流,然后把它们通过另外一个流

     

    index.js:

    require('colors');
    console.log('smashing node'.rainbow);

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    function c(){
        b();
    };
    function b(){
        a();
    };
    function a(){
        throw new Error('here');
    };
    c();

    function c(){
        b();
    };
    function b(){
        a();
    };
    function a(){
        setTimeout(function(){
            throw new Error('here');
        },10);
    };
    c();

     

     

     

  • 相关阅读:
    一口一口吃掉Hibernate(八)——Hibernate中inverse的用法
    一口一口吃掉Hibernate(七)——继承映射
    一口一口吃掉Hibernate(六)——多对多关联映射
    一口一口吃掉Hibernate(五)——一对多单向关联映射
    一口一口吃掉Hibernate(四)——多对一单向关联映射
    Hibernate给表和字段设置前后缀及分隔符
    Hibernate中Session之get和load方法的真正区别
    oracle中关于日期的获取
    java中去掉字符串空格
    实现html与html 页面之间传递参数以及接收参数
  • 原文地址:https://www.cnblogs.com/JasonPeng1/p/12049787.html
Copyright © 2011-2022 走看看