详解一个基于套接字实现长连接的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 相关文章推荐
js版本A*寻路算法
Dec 22 Javascript
学习ExtJS TextField常用方法
Oct 07 Javascript
层序遍历在ExtJs的TreePanel中的应用
Oct 16 Javascript
提高网站性能之 如何对待JavaScript
Oct 31 Javascript
动态加载外部javascript文件的函数代码分享
Jul 28 Javascript
处理及遍历XML文档DOM元素属性及方法整理
Aug 23 Javascript
在JavaScript中判断整型的N种方法示例介绍
Jun 18 Javascript
跟我学习javascript的异步脚本加载
Nov 20 Javascript
JQuery日历插件My97DatePicker日期范围限制
Jan 20 Javascript
微信小程序 地图(map)实例详解
Nov 16 Javascript
JavaScript运动框架 链式运动到完美运动(五)
May 18 Javascript
jQuery判断自定义属性data-val用法示例
Jan 07 jQuery
微信小程序学习笔记之跳转页面、传递参数获得数据操作图文详解
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 什么是PEAR?(第二篇)
2009/03/19 PHP
PHP 提取图片img标记中的任意属性的简单实例
2013/12/10 PHP
PHP中unset,array_splice删除数组中元素的区别
2014/07/28 PHP
跟我学Laravel之安装Laravel
2014/10/15 PHP
php面向对象中static静态属性与方法的内存位置分析
2015/02/08 PHP
我见过最全的个人js加解密功能页面
2007/12/12 Javascript
分享14个很酷的jQuery导航菜单插件
2011/04/25 Javascript
JQuery实现绚丽的横向下拉菜单
2013/12/19 Javascript
Select标签下拉列表二级联动级联实例代码
2014/02/07 Javascript
eclipse导入jquery包后报错的解决方法
2014/02/17 Javascript
jQuery中[attribute]选择器用法实例
2014/12/31 Javascript
js数组去重的5种算法实现
2015/11/04 Javascript
JS实时弹出新消息提示框并有提示音响起的实现代码
2016/04/20 Javascript
PHP抓取HTTPS内容和错误处理的方法
2016/09/30 Javascript
javascript操作cookie
2017/01/17 Javascript
vue脚手架中配置Sass的方法
2018/01/04 Javascript
解决vue中监听input只能输入数字及英文或者其他情况的问题
2018/08/30 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
vue使用自定义事件的表单输入组件用法详解【日期组件与货币组件】
2020/06/01 Javascript
[42:24]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第三场 11.27
2020/12/01 DOTA
Python ORM框架SQLAlchemy学习笔记之数据查询实例
2014/06/10 Python
跟老齐学Python之编写类之三子类
2014/10/11 Python
在Python中操作文件之truncate()方法的使用教程
2015/05/25 Python
TensorFlow 合并/连接数组的方法
2018/07/27 Python
对python打乱数据集中X,y标签对的方法详解
2018/12/14 Python
浅谈python 读excel数值为浮点型的问题
2018/12/25 Python
python实现一个猜拳游戏
2020/04/05 Python
Python压缩模块zipfile实现原理及用法解析
2020/08/14 Python
Python命令行参数定义及需要注意的地方
2020/11/30 Python
pandas将list数据拆分成行或列的实现
2020/12/13 Python
组织关系转移介绍信
2014/01/16 职场文书
个人三严三实对照检查材料
2014/09/25 职场文书
大学生在校表现评语
2014/12/31 职场文书
2015年圣诞节活动总结
2015/03/24 职场文书
2015年度公共机构节能工作总结
2015/05/26 职场文书
MySQL性能压力基准测试工具sysbench的使用简介
2021/04/21 MySQL