一個基於套接字實現長鏈接的express

一個基於套接字實現長鏈接的小型expressexpress

邏輯: 首先把routerUrl目錄下的函數初始化緩存起來,經過Router.request調用緩存起來的
函數,這個函數其實是register.set方法,主要是開始運行函數鏈,經過
register.next 運行下一個函數。緩存

函數流 main.js --> Router.request --> register.set --> register.next --> sock.writeapp

main.jssocket

'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文件async

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文件ui

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;

註冊文件this

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的思想,要用在實際開發中還須要斷線重連,優化鏈接,異常處理等功能。url

相關文章
相關標籤/搜索