02、NodeJS-基础

2018-10-20  本文已影响4人  王梓懿_1fbc

一、异步编程

  - Node 采用 Chrome V8 引擎处理 JavaScript 脚本, V8 最大特点就是单线程运行,一次只能运行一个任务
  - Node 大量采用异步操作(asynchronous operation),即任务不是马上执行,而是插在任务队列的尾部,等到前面的任务运行完后再执行
  - 提高代码的响应能力

Node大量采用异步操作,即任务不是马上执行,而是直接插入任务队列的尾部,等前面任务执行完成后再只执行。异步执行,而不是单线程执行(一次只能执行一个任务),这大大提高代码的响应能力。
【Node中,所有会发生阻塞的操作都是异步的。】

  - setTimeout()
  - ajax
  - 文件操作
  ...

  - 回调函数一定作为参数的最后一个参数出现:
    function foo1(name, age, callback) { }
    function foo2(value, callback1, callback2) { }

  - 回调函数的第一个参数默认接收错误信息,第二个参数才是真正 的回调数据(便于外界获取调用的错误情况):
     foo1('李明', 19, function(error, data) { 
        if(error) throw error;
          console.log(data);
      });

***错误优先: ***因为之后的操作大多数都是异步的方式,无法通过 try catch 捕获异常; 所以在node中错误优先的回调函数,第一个参数为上一步的错误信息。

  - 异步事件驱动的代码不容易阅读
  - 不容易调试
  - 不容易维护

二、进程和线程

  - 一个正在运行 的应用程序都称之为进程;
  - 每一个应用程序都至少有一个进程;
  - 进程是用来给应用程序提供一个运行的环境;
  - 进程是操作系统为应用程序分配资源的一个单位;

  - 用来执行应用程序中的代码;
  - 在一个进程内部,可以有很多的线程;
  - 在一个线程内部,同时只可以干一件事;
  - 而且传统的开发方式大部分都是 I/O 阻塞的;
  - 所以需要多线程来更好的利用硬件资源;
  - 给人带来一种错觉:线程越多越好;

多线程同时执行,真实情况并不是"同时",因为CPU只有一个;
线程问题: 线程创建需要耗费资源,线程数量也不能无限添加,线程同步操作,线程间数据共享,CPU中线程间的切换有上下文的转换是需要耗时的....
在node中,实现异步非阻塞操作,并不是使用多线程实现了(常规的异步非阻塞是通过多线程实现的)。*** Node.js在设计上也是比较大胆,它以单进程、单线程模式运行。事件驱动机制是Node.js通过内部单线程高效率地维护事件循环队列来实现的,没有多线程的资源占用和上下文切换,这意味着面对大规模的http请求,Node.js凭借事件驱动搞定一切。***

三、事件驱动

事件驱动是NodeJS中一大特性。事件驱动,就是通过监听事件的状态变化来作出相应的操作。例如文件存在,文件不存在,文件读取完毕,文件读取错误,触发对应的状态,之后通过回调函数进行处理。

在美国去看医生,需要填写大量表格,比如保险、个人信息之类,传统的基于线程的系统(thread-based system),接待员叫到你,你需要在前台填写完成这些表格,你站着填单,而接待员坐着看你填单。你让接待员没办法接待下一个客户,除非完成你的业务。想让这个系统能运行的快一些,只有多加几个接待员,人力成本需要增加不少。

基于事件的系统(event-based system)中,当你到窗口发现需要填写一些额外的表格而不仅仅是挂个号,接待员把表格和笔给你,告诉你可以找个座位填写,填完了以后再回去找他。你回去坐着填表,而接待员开始接待下一个客户。你没有阻塞接待员的服务。
你填完表格,返回队伍中,等接待员接待完现在的客户,你把表格递给他。如果有什么问题或者需要填写额外的表格,他给你一份新的,然后重复这个过程。
这个系统已经非常高效了,几乎大部分医生都是这么做的。如果等待的人太多,可以加入额外的接待员进行服务,但是肯定要比基于线程模式的少得多。

四、模块化结构

  - 文件模块
      就是我们自己写的功能模块文件
  - 核心模块
      Node 平台自带的一套基本的功能模块,也有人称之为 Node平台的 API
  - 第三方模块
      社区或第三方个人开发好的功能模块,可以直接拿回来用

  - new compute.js  创建模块(一个模块就一个文件)
  - module.exports = {}  导出成员
  - var comp = require('./compute.js')  载入模块
  - comp.add(1, 1)  使用模块

五、定义模块

  -  __dirname
      用于获取当前文件所在目录的完整路径
      在 REPL 环境无效
  -  __filename
      用来获取当前文件的完整路径
      在 REPL 环境同样无效
  - module 
      模块对象
  - exports
      映射到module.exports的别名
  - require()
      require.cache
      require.extensions
      require.main
      require.resolve()

文件操作中必须使用绝对路径;

  – module.id 模块的识别符,通常是带有绝对路径的模块文件名;
  - module.filename 模块定义的文件的绝对路径;
  – module.loaded 返回一个布尔值,表示模块是否已经完成加载;
  – module.parent 返回一个对象,表示调用该模块的模块;
  – module.children 返回一个数组,表示该模块要用到的其他模块;
  – module.exports 表示模块对外输出的值;

  - 一个新的 JS 文件就是一个模块;
  - 一个合格的模块应该是有导出成员的,否则模块就失去了定义的价值;
  - 模块内部是一个独立(封闭)的作用域(模块与模块之间不会冲突);
  - 模块之间必须通过导出或导入的方式协同;
  - 导出方式
      exports.name = value;
      module.exports = { name: value };
  - module.exports是用于为模块导出成员的接口;
  - exports是指向module.exports的别名,相当于 在模块开始的时候执行
      var exports = module.exports;
  - 一旦为 module.exports 赋值,就会切断之前两者的相关性;
  - 最终模块的导出成员以 module.exports 为准;

1、每个模块的内部都是私有空间,不会污染全局作用域;
2、模块可以多次加载,但是只会在第一次加载时运行一次, 然后运行结果就被缓存了,以后再加载,就直接读取缓 存结果;
3、模块加载的顺序,按照其在代码中出现的顺序;

六、载入模块

  require('./module');

  // 1、此时文件按 JS 文件执行
  require('./module.js');
  // 2、此时文件按 JSON 文件解析
  require('./module.json');
  // 3、此时文件预编译好的 C++ 模块执行
  require('./module.node');

  - 通过 ./ 或 ../ 开头:则按照相对路径从当前文件所在文件夹开始寻找模块
      require('../file.js');   // 上级目录下找 file.js 文件
  - 通过 / 开头:则以系统根目录开始寻找模块
      require('/Users/zyz/Documents/file.js');  // 以绝对路径的方式找
  - 如果参数字符串不以“./“ 或 ”/“ 开头,则表示加载 的是一个默认提供的核心模块(位于 Node 的系统安 装目录中)
      require('fs');   // 加载核心模块中的文件系统模块
  - 或者从当前目录向上搜索 node_modules 目录中的文件
      require('my_module'); // 各级 node_modules文件夹中搜索 my_module.js 文件;

require('my_module'); 开始是在核心模块中查找,这个其实不是核心模块;接着各级 node_modules文件夹中搜索

    //  模块的缓存的删除
    Object.keys(require.cache).forEach( (key) => {
        delete require.cache[key];
    } );

  // 缓存的问题 -- 方式1
  module.exports = () => {
      return {time: new Date()};
  }
  // 缓存的问题 -- 方式2
    function fn(){
        return {time: new Date()};
     }
    module.exports = {fn};

作者:西门奄
链接:https://www.jianshu.com/u/77035eb804c3
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

上一篇下一篇

猜你喜欢

热点阅读