Node.js基础笔记(1)

一. 模块

1. 载入策略

原生模块已经被转成二进制执行文件,加载快。
模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。。

(1)文件模块

由module原生module模块实现。该原生模块启动时已经被加载。
1) require参数
原生模块
相对路径文件模块
绝对路径文件模块
非原生文件模块
2)所有代码都运行在模块作用域,不会污染全局作用域
导出方式:

exports.name = value;
module.exports = { name: value };

var exports = module.exports;
一旦为 module.exports 赋值,就会切断之前两者的相关性;
最终模块的导出成员以 module.exports 为准

3)require文件查找策略
从文件模块缓存中加载
从原生模块中加载
从文件加载

require('./module');      //先找js
// 此时文件按 JS 文件执行
require('./module.js');    //js没找到  找json
// 此时文件按 JSON 文件解析
require('./module.json');   //json没找到  找node
// 此时文件预编译好的 C++ 模块执行
require('./module.node');   //node没找到找module模块下的index.js
// 载入目录module目录中的 package.json 中main指向的文件
require('./module/index.js');
// 载入目录module 中的default.js文件
条件 描述 例子
./ 或 ../ 开头 按照相对路径从当前文件所在文件夹开始寻找模块; require(‘../file.js’); => 上级目录下找 file.js 文件
通过 / 开头 则以系统根目录开始寻找模块 require(‘/Users/iceStone/Documents/file.js’); => 以绝对路径的方式找
不以“./“ 或 ”/“ 开头 则表示加载的是一个默认提供的核心模块(位于 Node 的系统安装目录中) require(‘fs’); => 加载核心模块中的文件系统模块
或者从当前目录向上搜索 node_modules 目录中的文件 require(‘my_module’); => 各级 node_modules 文件夹中搜索 my_module.js 文件
传入的是一个目录的路径 自动查看该目录的 package.json 文件,然后加载 main 字段指定的入口文件
package.json文件没有main字段,或者根本就没有package.json文件,则默认找目录下的 index.js 文件作为模块 require(‘./calcuator’); => 当前目录下找 calculator 目录中的 index.js 文件

4) 包
require没找到文件时,会将文件名作为一个包来尝试加载,package.json文件的main字段定义了默认加载的文件,如之前的index.js。
package.json字段:

字段 描述
name 包名 npm上是唯一的
description 简介
version 版本号
keywords 关键字数组,用于npm中分类搜索
maintainers 维护者数组
contributors 贡献者数组
bugs 提交bug网址
licenses 许可证
repositories 源代码地址数组
dependencies 包依赖,npm会自动加载依赖

5) 模块中的全局环境

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

2. 内置模块

path:处理文件路径。
fs:操作(CRUD)文件系统。
child_process:新建子进程。
util:提供一系列实用小工具。
http:提供 HTTP 服务器功能。
url:用于解析 URL。
querystring:解析 URL 中的查询字符串。
crypto:提供加密和解密功能。

二. 事件机制

1. 事件

统一了前后端javascript编程模型
利用事件机制充分利用异步IO突破单线程编程模型的性能瓶颈

events.EventEmitter事件监听器

操作 描述
addListener/on 多次添加监听
once 触发发一次后删除监听
removeListener 根据函数删除监听
removeAllListeners 删除该事件上的所有监听
emit 触发事件

对一个时间加十个监听器就会得到一个警告,emitter.setMaxListeners(0)可去掉这个警告
运行期间触发error事件,EventEmitter交于事件error监听处理,如果没有添加监听,抛出异常,若没有异常捕获,则会引起线程退出。

//addListener removeListener  EventEmitter.listenerCount
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.addListener("testEvent", function() {
    console.log("testEvent");
});
event.addListener("testEvent", function() {
    console.log("testEvent");
});

var l2 = function() {
    console.log("testEvent");
};
event.on("testEvent", l2);

event.emit("testEvent");
console.log(EventEmitter.listenerCount(event, "testEvent"));

event.removeListener("testEvent", l2);
console.log(EventEmitter.listenerCount(event, "testEvent"));
/*输出:
    testEvent
    testEvent
    testEvent
    3
    2
*/

2.事件的继承

node中提供继承方法utils.inherit()

三. 文件系统

1. fs的同步与异步

fs模块对文件的几乎所有操作都有同步和异步两种形式
readFile() 和 readFileSync()
区别:
同步调用会阻塞代码的执行,异步则不会
异步调用会将读取任务下达到任务队列,直到任务执行完成才会回调
异常处理方面,同步必须使用 try catch 方式,异步可以通过回调函数的第一个参数

2. 文件读取

(1)基本方法

方式 代码
异步 fs.readFile(file[,options], callback(err, data){})
同步 fs.readFileSync(file[,options])
文件流 fs.createReadStream(path[,options])
//异步
console.time('async');
fs.readFile(path.join(__dirname, './images/1.jpg'), (err) => {
    if(err) {
        throw error;
    }
});
console.timeEnd('async');
//同步
console.time("sync");
try {
    let img = fs.readFileSync(path.join(__dirname, 
    './images/1.jpg'));
}catch(error) {
    throw error;
}
console.timeEnd("sync");

//文件流
const iconv = require('iconv-lite');   //解码中文

var data = '';
var streamReader = fs.createReadStream(path.join(__dirname, 
'./传奇.lrc'));
streamReader.on('data', (chunk) => {
    //部分文件流
    console.log(iconv.decode(chunk, 'gbk'));
});
streamReader.on('end', () => {});

歌词解析读取案例

//逐行读取
const iconv = require('iconv-lite');
fs.readFile(path.join(__dirname, './传奇.lrc'), (err, data) => {
    var lines = iconv.decode(data, 'gbk').split('\r\n');
    var regex = /\[(\d{2})\:(\d{2})\.(\d{2})\](.+)/;
    //[03:07.57]想你时你在天边
    lines.forEach((line) => {
        var matches = regex.exec(line);
        if(matches) {
            var m = parseFloat(matches[1]);
            var n = parseFloat(matches[2]);
            var f = parseFloat(matches[3]);
            var lyric = matches[4];
            setTimeout(() => {
                console.log(lyric);
            }, m*60*1000 + n*1000 + f);
        }else {
            //console.log("不是标准行" + line);
        }
    });
});

(2)readline实现上例

const fs = require('fs');
const path = require('path');
const iconv = require('iconv-lite');
const readline = require('readline');
var filename = path.join(__dirname, ''./传奇.lrc'');
var streamReader = fs.createReadStream(filename)
  .pipe(iconv.decodeStream('gbk'));
// 利用readline读取
var rl = readline.createInterface({ input: streamReader });
var begin = new Date().getTime();
rl.on('line', (line) => {
  task(line, begin);
});
var regex = /\[(\d{2})\:(\d{2})\.(\d{2})\]\s(.+)/;
function task(line, begin) {
  var matches = regex.exec(line);
  if (matches) {
    var m = parseFloat(matches[1]);
    var s = parseFloat(matches[2]);
    var f = parseFloat(matches[3]);
    var lyric = matches[4]; 
    var offset = new Date().getTime() - begin;
    setTimeout(() => {
      console.log(lyric);
    }, m * 60 * 1000 + s * 1000 + f - offset);
  } else {
    //console.log(line);
  }
}

3.文件写入

方式 代码
异步文件写入 fs.writeFile(file,data[,option],callback(err))
同步文件写入 fs.writeFileSync(file,data,[,option])
流式文件写 fs.createWriteStream(path[,option])
异步追加 fs.appendFile(file,data[,options],callback(err))
同步追加 fs.appendFileSync(file,data[,options])

4. 其它文件操作

方式 代码
获取文件信息 fs.stat(path, callback(err, stats)) fs.statSync(path)返回fs.stats实例
移动文件 fs.rename(oldpath, newpath)
重命名文件或目录 fs.rename(oldPath,newPath,callback) fs.renameSync(oldPath,newPath)
删除文件 fs.unlink(path,callback(err)) fs.unlinkSync(path)

5. 目录操作

方式 代码
创建一个目录 fs.mkdir(path[,model],callback) fs.mkdirSync(path[,model])
删除一个空目录 fs.rmdir(path,callback) fs.rmdirSync(path)
读取一个目录 fs.readdir(path,callback(err,files)) fs.readdirSync(path) // => 返回files

6. 监视文件变化

fs.watchFile(filename[, options], listener(curr,prev))
options:{persistent,interval}
fs.watch(filename[,options][,listener])

猜你喜欢

转载自blog.csdn.net/weixin_39265000/article/details/79506701
今日推荐