详解一个基于套接字实现长连接的express


Posted in Javascript onMarch 28, 2019

逻辑: 首先把routerUrl目录下的函数初始化缓存起来,通过Router.request调用缓存起来的函数,这个函数实际上是register.set方法,主要是开始运行函数链,通过register.next 运行下一个函数。

函数流 main.js --> Router.request --> register.set --> register.next --> sock.write

main.js

'use strict';
const routerUrl = 'router'; // 当前目录下的router地址
const Router = require('./net/Router'); // 初始化路由
const net = require('net');
const port = '3000';
Router.init(routerUrl);
const app = sock => {
  sock.on('data', function (data) {
    try {
      Router.request(data, sock);
    } catch (error) {
      console.log(error)
    }
  });

  sock.on('error', (err) => {
    console.log(err)
  })

  // 为这个socket实例添加一个"close"事件处理函数
  sock.on('close', function (data) {
    console.log('clone')
  })
}
const server = net.createServer(app);

server.listen(port, () => {
  console.log(`Startu in env ${process.env.NODE_ENV || 'development'} on port ${port}`);
});

server.on('error', (err) => {
  console.log(err)
})

路由加载:

Router.js文件

const fs = require('fs');
const _ = require('lodash');
var path = require("path");
var ROOT_PATH = path.resolve(__dirname);
class Router {
  constructor() {
    this.routeMap = {};
  }
  /**
   * 通过routerUrl来匹配目录下的文件,加载进来
   * @param {*} routerUrl
   */
  init(routerUrl) {
    let files = fs.readdirSync(path.join(ROOT_PATH, `../${routerUrl}`));
    return _.reduce(files, (config, file) => {
      let svc = require(path.join(ROOT_PATH, `../${routerUrl}/${file}`));
      this.routeMap = {
        [file.split('.')[0]]: svc.get()
      };
    }, {})
  }
  /**
   * 通过url匹配加载的router, 其他字段可自定义,url这里的逻辑也可改成配置文件进行配置,类似于protobuf
   * @param {*} data {url, body}
   * @param {*} sock
   */
  request(data, sock) {
    try {
      this.routeMap[result.url.split('/')[1]][result.url.replace(`/${result.url.split('/')[1]}`, '')](data, sock);
    } catch (error) {
      sock.write(error);
    }
  }
}

module.exports = new Router();

中间件:

register.js文件

const Next = require('./next');

class Register {
  constructor() {
    this._init = {};
  }
  <!-- 初始化router函数,开始运行函数链 -->
  set(url, ...handlers) {

    this._init[url] = async (data, sock) => {
      try {
        let next = new Next(handlers);
        next.run(data, sock);  
      } catch (error) {
        sock.write(error);
      }
    };
  }
  <!-- 获取初始化的router函数 -->
  get() {
    return this._init;
  }
}

module.exports = new Register();

nest.js文件

class Next {
  constructor(stack) {
    this.index = 0;
    this.stack = stack;
    this.data = null;
    this.sock = null;
  }
  <!-- 运行中间件 -->
  run(data, sock) {
    this.data = data;
    this.sock = sock;
    this.stack[this.index](data, sock, this.next.bind(this));
  }
  <!-- 调到下一个中间件,若带参数就跳到第arguments[0]步 -->
  next() {
    if (arguments[0] && arguments[0] === +arguments[0] && +arguments[0] < this.stack.length) {
      this.index = +arguments[0];
      return this.run(data, this.sock);
    }
    this.index++;
    this.run(this.data, this.sock);
  }
}

module.exports = Next;

注册文件

const init = require('../net/register');

init.set('/test',
  (data, sock, next) => {
    next()
  },
  async (data, sock) => {
    try {
      sock.write(test);
    } catch (e) {
      sock.write(e);
    }
  });

总结:这个项目只是用来歇息express的思想,要用在实际开发中还需要断线重连,优化连接,异常处理等功能。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 生成指定范围数值随机数
Jan 09 Javascript
jQuery中获取checkbox选中项等操作及注意事项
Nov 24 Javascript
jquery实现页面图片等比例放大缩小功能
Feb 12 Javascript
js分页工具实例
Jan 28 Javascript
微信小程序 wx.request(OBJECT)发起请求详解
Oct 13 Javascript
vue-music关于Player播放器组件详解
Nov 28 Javascript
微信小程序实现YDUI的ScrollNav组件
Feb 02 Javascript
Vue在页面右上角实现可悬浮/隐藏的系统菜单
May 04 Javascript
jQuery实现当拉动滚动条到底部加载数据的方法分析
Jan 24 jQuery
Node.js之readline模块的使用详解
Mar 25 Javascript
微信小程序 textarea 层级过高问题简单解决方案
Oct 14 Javascript
在Chrome DevTools中调试JavaScript的实现
Apr 07 Javascript
微信小程序学习笔记之跳转页面、传递参数获得数据操作图文详解
Mar 28 #Javascript
微信小程序学习笔记之表单提交与PHP后台数据交互处理图文详解
Mar 28 #Javascript
深入理解es6块级作用域的使用
Mar 28 #Javascript
详解在网页上通过JS实现文本的语音朗读
Mar 28 #Javascript
详解React服务端渲染从入门到精通
Mar 28 #Javascript
微信小程序学习笔记之函数定义、页面渲染图文详解
Mar 28 #Javascript
JavaScript刷新页面的几种方法总结
Mar 28 #Javascript
You might like
PHP面向对象的使用教程 简单数据库连接
2006/11/25 PHP
PHP面向对象学习笔记之二 生成对象的设计模式
2012/10/06 PHP
php数组去重实例及分析
2013/11/26 PHP
XAMPP安装与使用方法详细解析
2013/11/27 PHP
PHP正则表达式之捕获组与非捕获组
2015/11/06 PHP
php和nginx交互实例讲解
2019/09/24 PHP
Laravel等框架模型关联的可用性浅析
2019/12/15 PHP
IE6下CSS图片缓存问题解决方法
2010/12/09 Javascript
jquery的index方法实现tab效果
2011/02/16 Javascript
javascript中的循环语句for语句深入理解
2014/04/04 Javascript
js获取会话框prompt的返回值的方法
2015/01/10 Javascript
js带点自动图片轮播幻灯片特效代码分享
2015/09/07 Javascript
JS阻止事件冒泡行为和闭包的方法
2016/06/16 Javascript
基于JavaScript实现的快速排序算法分析
2017/04/14 Javascript
jQuery实现QQ空间汉字转拼音功能示例
2017/07/10 jQuery
详解如何使用webpack在vue项目中写jsx语法
2017/11/08 Javascript
jquery-file-upload 文件上传带进度条效果
2017/11/21 jQuery
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
Vue单页面应用保证F5强刷不清空数据的解决方案
2018/01/31 Javascript
vue3.0 CLI - 3.2 路由的初级使用教程
2018/09/20 Javascript
JavaScript 类的封装操作示例详解
2020/05/16 Javascript
基于element-ui封装可搜索的懒加载tree组件的实现
2020/05/22 Javascript
vue中实现弹出层动画效果的示例代码
2020/09/25 Javascript
[44:50]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第二局
2016/02/26 DOTA
解决Python下imread,imwrite不支持中文的问题
2018/12/05 Python
Python制作微信好友背景墙教程(附完整代码)
2019/07/17 Python
浅谈keras的深度模型训练过程及结果记录方式
2020/01/24 Python
Python collections.defaultdict模块用法详解
2020/06/18 Python
Chupi官网:在爱尔兰手工制作的订婚、结婚戒指和精美珠宝
2020/09/28 全球购物
关于递归的一道.NET面试题
2013/05/12 面试题
投资协议书范本
2014/04/21 职场文书
厨房领班竞聘演讲稿
2014/04/23 职场文书
教师党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
格列夫游记读书笔记
2015/07/01 职场文书
2019幼儿教师求职信(3篇)
2019/09/20 职场文书
python 爬取哔哩哔哩up主信息和投稿视频
2021/06/07 Python