node核心设计模式

node核心设计模式


references:

《Node.js 设计模式(第 2 版)》【爱尔兰】Mario Casciaro(马里奥•卡西罗) / 【意大利】Luciano Mammino(卢西安诺•马米诺)

简单介绍

node哲学思想

  • 小核心:保持核心功能的最小集合。
  • 小模块:在NPM(官方软件包管理器)的帮助下,node可以解决依赖地狱问题。==> Don’t repeat yourself
  • 小接触面
es6的一点知识
    // 关于 weakMap和weakSet
    let obj={};
    const map=new WeakMap();
    map.set(obj,{key:'some_value'});
    console.info(map.get(obj));
    // 只剩下引用的时候,对象作为主键可以用来进行垃圾回收
    obj=undefined; // now obj and the associated data in the map will be cleaned up in the next gc cycle
    console.info(map);


    let obj1={key:'val1'};
    let obj2={key:'val2'};
    const set=new WeakSet([obj1,obj2]);
    console.info(set.has(obj1));
    // 只剩下引用的时候被垃圾回收
    obj1=undefined; // now obj1 will be removed from the set
    console.info(set.has(obj1));

reactor模式

阻塞I/O

传统的阻塞I/O编程,与I/O请求相对应的函数调用将阻塞线程的执行。

非阻塞I/O

这种模式下,系统调用总是立即返回,而无需等待数据读取或者写入。访问这种非阻塞I/O的最基本模式是在循环内主动轮询资源,直到返回一些实际数据即忙碌等待。

reactor模式通过阻塞来处理I/O,直到一组被观察资源的新事件可用,然后将每个事件分派到相关联的处理程序来作出反应。

image]
其中「绑定」是用来负责包装和暴露libuv和JavaScript其他低级功能。

node基本设计模式

node回调约定

  • 回调函数置于尾部
  • 暴露错误优先
fs.readFile('foo.txt','utf8',(err,data)=>{
    if(err){
        handleError(err);
    }else{
        process(data);
    }
})

  • 传播错误:传播错误时建议使用return语句,这样可以确保一旦回调函数函数被调用就退出函数。
  • 未捕获异常
// todo  说实话没有看懂

模块系统及其模式

node模块遵循commonJS模块规范

  • require函数是同步的,因此module.exports也是同步的
  • 解析算法
    • 文件模块
    • 核心模块
    • 包模块
      对于文件和包模块,单个文件和目录都可以与moduleName匹配,特别的,解析算法将尝试匹配以下内容:
    • .js
    • /index.js
    • 在/package.json的main属性中制定的目录/文件
导出函数

将整个module.exports变量重新分配给一个函数。

module.exports=(message)=>{
    console.info(`info:${message}`);
}


// 扩展

module.exports.verbose=message=>{
    console.info(`verbose:${message}`);
}

node 提倡单一职责原则:(single responsibility principle,SRP)

导出实例
// Logger是一个构造函数
module.exports.logger=Logger;

观察者模式

EventEmitter类允许我们将一个或者多个函数注册为监听器,当一个特定的事件类型被触发时,它将被调用。

references:

Node中EventEmitter理解与简单实现

Node.js EventEmitter类源码浅析


// EventEmitter简单实现,但是真正的源码处理了很多边界条件,具体可以参考:https://www.jianshu.com/p/3dc51474c96c

function EventEmitter() {
    this.events = {};  //所有事件监听函数放在这个对象里保存
    this._maxListeners = 10; //监听函数最多10个
}
//给制定函数绑定事件处理函数
EventEmitter.prototype.on = EventEmitter.prototype.addEventListener = function (type,listener) {
    if(this.events[type]){
        this.events[type].push(listener);
        if(this._maxListeners != 0 && this.events[type].length > this._maxListeners){
            console.error('MaxListenersExceededWarning: Possible EventEmitter memory leak detected.\n');
        }
    }else {
        this.events[type] = [listener];
    }
};
EventEmitter.prototype.emit = function (type, ...rest) {
    if(this.events[type]){
        //遍历触发函数数组   apply把this指向当前对象  解构rest
        this.events[type].forEach((listener)=>listener.apply(this,rest));
    }
};
EventEmitter.prototype.removeListener =  function(type,listener) {
    if (this.events[type]){
        this.events[type] = this.events[type].filter(l=>l!==listener);
        //使用filter过滤数组
    }
};
有关EventEmitter的一些特点
  • 传播错误

为了避免正常出现错误的情况以及事件是异步,事件循环中出现错误的情况,约定发出error事件并为其注册事件监听器。

const emitter=new EventEmitter();
emitter.on('error',err=>{
    console.info(err.message);
})

  • 使任何对象可观察

通过扩展EventEmitter来使任何对象可观察

class Test extends EventEmitter{}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值