Node 功能的组织及重用 —— ==模块==

  • Node 模块打包代码是为了重用,但它们不会改变全局作用域,避免了污染命名空间。

  • exports 对象的属性:模块返回多个函数或变量

  • module.exports:模块只返回一个函数或变量

  • 模块既可以是一个文件,也可以是包含一个或多个文件的目录:

  • Node 独特的模块引入机制:先找核心模块,然后是当前目录,最后是 node_modules。(假设引入的模块是./currency。如果省略./,只写 currency ,Node 会遵照如下流程图搜寻这个模块)

  • require 是 Node 中少数几个同步 I/O 操作之一。

  • Node 对 json 存在原生导入支持:如果没有指明引入得是 js 文件,Node 也会检查 json 文件,json 文件是作为 JavaScript 对象加载的。

  • 两种导出规范同时存在时,则会返回 module.exports,而 exports 会被忽略。

探究导出的究竟是什么

  • 最终在程序里导出的是 module.exports

exports 只是对 module.exports 的一个全局引用,最初被定义为一个可以添加属性的空对象。

exports.myFunc 只是 module.exports.myFunc 的简写。所以,如果把 exports 设定为别的,就打破了 module.exports 和 exports 之间的引用关系,可以使用 module.exports = exports = myFunc 让两者恢复原来的引用关系。

注意事项

  • 如果模块是目录,在模块目录中定义模块的文件必须被命名为 index.js,除非在这个目录中的 package.json 里特别指明 "main" 键的主文件路径。

  • Node 能把模块作为对象缓存起来。

服务端异步编程 - 回调/事件监听/流程控制工具

  • ==回调==:来自 Web 服务器的 HTML 响应,从 JSON 文件中获取标题并返回一个 Web 页面

    // 源代码中存在三层嵌套,可将其抽离出来封装函数
    const  http = require('http')
    const  fs = require('fs')
    // 创建HTTP服务器并用回调定义响应逻辑
    http.createServer((req, res) => {
    	if (req.url == '/') {
    		// 读取JSON文件并用回调定义如何处理其中的内容
    		fs.readFile('./titles.json', (err, data) => {
    			// 从JSON文本中解析数据
    			const  titles = JSON.parse(data.toString())
    			// 读取HTML模板,并在加载完成后使用回调
    
    			fs.readFile('./template.html', (err, data) => {
    				const  tmpl = data.toString()
    				// 组装HTML页面以显示博客标题
    				const  html = tmpl.replace('%', titles.join('</li><li>'))
    				res.writeHead(200, { 'Content-Type':  'text/html' })
    				res.end(html)
    			})
    		})
    	}
    }).listen(8000, '127.0.0.1')
    
  • ==事件监听==:以扩展事件监听器为例 —— 文件监视器

    • 继承自事件发射器类 events.EventEmitter(on、emit)

    • 功能:监听某文件目录下的文件变化,以对目录中每个文件执行 process 事件处理逻辑

      const  fs = require('fs')
      const  events = require('events')
      // 扩展EventEmitter,添加处理文件的方法
      class  Watcher  extends  events.EventEmitter {
      	constructor(watchDir, processedDir) {
      		super()
      		this.watchDir = watchDir
      		this.processedDir = processedDir
      	}
      	watch() {
      		// 处理watch目录中的所有文件
      		fs.readdir(this.watchDir, (err, files) => {
      			if (err) throw  err
      			for (var  index  in  files) {
      				this.emit('process', files[index])
      			}
      		})
      	}
      	// 添加开始监控的方法
      	start() {
      		// fs.watch 允许监视文件或目录的变化
      		fs.watch(this.watchDir, () => {
      			this.watch()
      		})
      	}
      }
      module.exports = Watcher
      // 在其他文件中 import Watcher
      // 定义 on 逻辑
      const  watcher = new  Watcher(watchDir, processedDir);
      watcher.on('process', (file) => {...})
      
  • 异步逻辑的顺序化 —— ==流程控制==