nodejs 搭建websocket长连接服务 实现前端页面调用第三方接口获取数据的实时更新

1、页面 与 js :

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>WebSocket Echo Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link href="../bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet" />
    <script src="../js/jquery-1.12.3.min.js"></script>
    <script src="../bootstrap-3.3.5/js/bootstrap.min.js"></script>
</head>

<body>
    <div class="vertical-center" >
        <div class="container">
            <h1>Stock Chart over WebSocket</h1>
            <div>{{message}}</div>
            <!--<button class="btn btn-primary">开始</button>
            <button class="btn btn-danger">停止</button>-->
            <table class="table" >
                <thead>
                    <tr>
                        <th>Symbol</th>
                        <th>Price</th>
                    </tr>
                </thead>
                <tbody >

                    <tr>
                        <td>
                            <h3>售票数</h3>
                        </td>
                        <td >
                            <h3><span class="label label-default" >{{numData}}</span></h3>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
    <script>
        var ws = new WebSocket("ws://localhost:8181");
        var stock_request = { "stocks": ["AAPL", "MSFT", "AMZN", "GOOG", "YHOO"] };
        var isClose = false;
        var stocks = {
            "AAPL": 0, "MSFT": 0, "AMZN": 0, "GOOG": 0, "YHOO": 0
        };
        function updataUI() {
            // debugger
            ws.onopen = function (e) {
                console.log(\'Connection to server opened\');
                isClose = false;
                //ws.send(JSON.stringify(stock_request));
                //ws.send(\'plese to conection\');
                //console.log("sened a mesg");
            }
            // UI update function
            var changeStockEntry = function (symbol, originalValue, newValue) {
                var valElem = $(\'#\' + symbol + \' span\');
                valElem.html(newValue.toFixed(2));
                if (newValue < originalValue) {
                    valElem.addClass(\'label-danger\');
                    valElem.removeClass(\'label-success\');
                } else if (newValue > originalValue) {
                    valElem.addClass(\'label-success\');
                    valElem.removeClass(\'label-danger\');
                }
            }
            // WebSocket message handler
            ws.onmessage = function (e) {
                var stocksData = JSON.parse(e.data);
                console.log(stocksData);
                for (var symbol in stocksData) {
                    if (stocksData.hasOwnProperty(symbol)) {
                        changeStockEntry(symbol, stocks[symbol], stocksData[symbol]);
                        stocks[symbol] = stocksData[symbol];
                    }
                }
            };
        }

        //updataUI();

        $(".btn-primary").click(function () {
            if (isClose) {
                ws = new WebSocket("ws://localhost:8181");
            }
            updataUI();
        });
        $(".btn-danger").click(function () {
            ws.close();
        });

        ws.onclose = function (e) {
            console.log("Connection closed", e);
            isClose = true;
        };




    </script>

    <script src="config/jquery-1.10.2.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script type="text/javascript">
        var app2 = new Vue({
            el: \'#test\',
            data: {
                message: \'页面加载于 \' + new Date().toLocaleString(),
                numData: 0,

            },
            mounted: function () {
            },
            methods: {

                init() {
                    //debugger
                    that = this;
                    var ws = new WebSocket(\'ws://localhost:8181\');
                    ws.onopen = function (e) {
                        console.log(\'开始连接服务器\')
                        // 发送消息

                        ws.send(\'连接到服务器\');

                    }
                    ws.onmessage = function (event) { // 监听消息
                        //debugger
                        //定时器设置数字变化的滚动效果
                        var number = event.data - that.numData;
                        var boo = number > 0 ? true : false;// boo = true动画效果为递增;boo = false动画效果为递减
                        setInterval(function () {
                            if (boo) {
                                //数字变大
                                number--;
                                if (number >= 0) {
                                    that.numData++;
                                    return that.numData;
                                }
                            }else {
                                //数字变小
                                number++;
                                if (number <= 0) {
                                    that.numData--;
                                    return that.numData;
                                }
                            }
                        }, 1);
                        

                        //that.numData = event.data;直接赋值没有动画效果,想要动画效果采用上面方法
                        console.log("监听到消息:" + that.numData);

                        //that.numData = msg.data.salesNum;
                    }
                    ws.onerror = function (evt) {
                        //产生异常
                        console.log("产生异常");
                    };
                    ws.onclose = function (evt) {
                        //产生异常
                        console.log("关闭");
                    };
                },
            },
            created: function () {
                this.init();
            }
        });
    </script>
</body>
</html>

nodejs 搭建server.js服务 :

var WebSocketServer = require(\'ws\').Server,
wss = new WebSocketServer({ port: 8181 });

//引入模块
var http = require(\'http\');
const querystring = require(\'querystring\');
var numData = -1;
var isTrue = false;
var clientStockUpdater;

//定义请求消息头
var headers = {
    \'XverifyApi\': \'fzY08dHMxkRRaDM9m7y+ptFf9qsVzmLb0enT7NRfBdAhtI0+iKv3Sg==\',
    \'XownerId\': \'fqszs\',
    \'XsysId\': \'sys-0\'
};
//定义请求消息url和头部
var options = {
    method: \'GET\',
    url: \'http//api.whlyw.net/bo/api/v1/big-data-ticket-market/list/res/sales\',
    headers: headers
};

function handleGetData() {
    //发送请求
    var request = require(\'request\');
    
    //console.log("33");

    request({
        url: \'http://api.whlyw.net/bo/api/v1/big-data-ticket-market/list/res/sales\',
        method: \'GET\',
        headers: headers
    }, function (error, response, body) {
       // console.log(response.statusCode)
        if (!error && response.statusCode == 200) {
           // console.log(JSON.parse(body)) // 请求成功的处理逻辑,注意body是json字符串  .data.salesNum
            console.log(\'页面数\' + numData);
            console.log(\'售票数\'+JSON.parse(body).data.salesNum);
            if (numData == JSON.parse(body).data.salesNum) {
                console.log(\'进入到页面数与售票数一致的方法中\');
                isTrue = false;
            } else {
                console.log(\'进入到页面数与售票数不一致的方法中\');
                numData = JSON.parse(body).data.salesNum
                isTrue = true;
            }  
            //console.log(numData);
            //return numData;
        }
    })

    //request(options, function (error, response, body) {
    //    console.log("33"+response.statusCode);
    //    if (!error && response.statusCode == 200) {
    //        console.log(body) // 请求成功的处理逻辑,注意body是json字符串
    //    }
    //});


    //var req = http.request(options, function (res) {
    //    console.log(res.statusCode);
    //    console.log(res.headers);
    //    res.setEncoding(\'utf-8\');
    //    res.on(\'data\', function (chunk) {
    //        //输出响应内容
    //        console.log("GGG"+chunk);

    //        ////将chunk转为对象
    //        //console.log(JSON.parse(chunk));
    //        ////通过对象调用各参数,不发散其他操作
    //        //console.log(JSON.parse(chunk).resultcode);
    //    });
    //    //res.on(\'end\', function () {
    //    //    console.log(\'响应结束********\');
    //    //});
    //});
    ////监控错误情况时报错
    //req.on(\'error\', function (e) {
    //    console.error(e);
    //});
    ////结束请求输入
    //req.end();
}



wss.on(\'connection\', function (ws) {
    var sendStockUpdates = function (ws) {
        //console.log("11", ws.readyState);
        if (ws.readyState == 1) {
            var stocksObj = {};
           // console.log("第一次");
            handleGetData();

            console.log("dd" + isTrue);
            if (isTrue) {
                console.log("发送前");
                ws.send(JSON.stringify(numData));
            }
        }
    }
    
    ws.on(\'message\', function (message) {
        //var stockRequest = JSON.parse(message);
        var stockRequest = message;
        console.log("收到消息", stockRequest);
        //clientStocks = stockRequest[\'stocks\'];
        //sendStockUpdates(ws);

        //setInterval第一次执行时会延迟对应时间,所以这里先执行该方法;如果每秒轮询就不用下面操作,下面的请求接口还有回调需要时间来的延迟
        //if (ws.readyState == 1) {
        //    var stocksObj = {};
        //    handleGetData();
        //    console.log("dd" + isTrue);
        //    if (!isTrue) {
        //        console.log("发送前");
        //        ws.send(JSON.stringify(numData));
        //    }
        //}

        clientStockUpdater = setInterval(function () {
           // console.log("第二次");
            sendStockUpdates(ws);
        }, 1000);
    });
    ws.on(\'close\', function () {
        if (typeof clientStockUpdater !== \'undefined\') {
            clearInterval(clientStockUpdater);
        }
    });
});

备注:

1、cmd打开命令窗口,进入到nodejs安装目录下,执行全局安装request模块命令:

npm i request -g 。

2、进入到项目所在目录执行启动node服务命令:node server.js。

3、再浏览器打开页面 初始化并创建websocket长连接,实时监听数据变化。