详解一个基于套接字实现长连接的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 相关文章推荐
自己动手制作jquery插件之自动添加删除行功能介绍
Oct 14 Javascript
jQuery ui插件的使用方法代码实例
May 08 Javascript
JavaScript插件化开发教程 (一)
Jan 27 Javascript
理解javascript中的原型和原型链
Jul 30 Javascript
JavaScript如何获取数组最大值和最小值
Nov 18 Javascript
原生js实现弹出层效果
Jan 20 Javascript
JavaScript和JQuery获取DIV值的方法示例
Mar 07 Javascript
JS操作xml对象转换为Json对象示例
Mar 25 Javascript
Vue.js通用应用框架-Nuxt.js的上手教程
Dec 25 Javascript
详解使用mpvue开发github小程序总结
Jul 25 Javascript
JavaScript函数式编程(Functional Programming)声明式与命令式实例分析
May 21 Javascript
使用 js 简单的实现 bind、call 、aplly代码实例
Sep 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
destoon二次开发常用数据库操作
2014/06/21 PHP
php mysql_list_dbs()函数用法示例
2017/03/29 PHP
php根据命令行参数生成配置文件详解
2019/03/15 PHP
jQuery Lightbox 图片展示插件使用说明
2010/04/25 Javascript
一些常用且实用的原生JavaScript函数
2010/09/08 Javascript
父元素与子iframe相互获取变量和元素对象的具体实现
2013/10/15 Javascript
js与jquery获取父元素,删除子元素的两种不同方法
2014/01/09 Javascript
JavaScript使用focus()设置焦点失败的解决方法
2014/09/03 Javascript
jQuery实现企业网站横幅焦点图切换功能实例
2015/04/30 Javascript
jQuery实现带有动画效果的回到顶部和底部代码
2015/11/04 Javascript
探讨JavaScript语句的执行过程
2016/01/28 Javascript
springMVC + easyui + $.ajaxFileUpload实现文件上传注意事项
2017/04/23 Javascript
nodejs入门教程一:概念与用法简介
2017/04/24 NodeJs
Bootstrap 模态对话框只加载一次 remote 数据的完美解决办法
2017/07/09 Javascript
详解nodejs通过代理(proxy)发送http请求(request)
2017/09/22 NodeJs
nodejs更新package.json中的dependencies依赖到最新版本的方法
2018/10/10 NodeJs
vue中的过滤器实例代码详解
2019/06/06 Javascript
Element Steps步骤条的使用方法
2020/07/26 Javascript
微信小程序实现日历签到
2020/09/21 Javascript
Python中使用ConfigParser解析ini配置文件实例
2014/08/30 Python
浅谈Python由__dict__和dir()引发的一些思考
2017/10/30 Python
Python视频爬虫实现下载头条视频功能示例
2018/05/07 Python
Python日期时间对象转换为字符串的实例
2018/06/22 Python
关于Pycharm无法debug问题的总结
2019/01/19 Python
Django框架视图介绍与使用详解
2019/07/18 Python
如何利用python给图片添加半透明水印
2019/09/06 Python
使用PyCharm进行远程开发和调试的实现
2019/11/04 Python
Python进程池Pool应用实例分析
2019/11/27 Python
如何理解python面向对象编程
2020/06/01 Python
PyQt5多线程防卡死和多窗口用法的实现
2020/09/15 Python
美国知名男士服饰品牌:Brooks Brothers(布克兄弟)
2016/08/25 全球购物
中国排名第一的外贸销售网站:LightInTheBox.com(兰亭集势)
2016/10/28 全球购物
好邻里事迹材料
2014/01/16 职场文书
“四风”问题的主要表现和危害思想汇报
2014/09/19 职场文书
2016年入党心得体会范文
2016/01/23 职场文书
MYSQL 表的全面总结
2021/11/11 MySQL