Vue


Vue+Nodejs 实现websocket

ajax 轮询:让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息 long poll 长轮询:其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起请求后,如果没消息,就一直不返回 Response 给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。

这两种方式,都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,被动性。服务端不能主动联系客户端,只能有客户端发起。上面这两种都是非常消耗资源的。


websocket:它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

node:

app.js

const webSocketService = require('./websocketservice')
webSocketService.listen()
websocketservice.js

const WebSocket = require('ws');

// 创建WebSocket服务端的对象,端口号是3001
const wss = new WebSocket.Server({
    port: 3001,
});

// 服务端开启了监听
module.exports.listen = () => {

    // client是客户端的连接socket对象
    wss.on('connection', client => {
        console.log('有客户端连接成功了');

        // 对客户端的每10秒推送
        setInterval(() => {
            client.send('这是服务端的定期推送(每5s)');
        }, 5000);

        // msg是客户端发给服务端的数据
        client.on('message', msg => {
            console.log('客户端发送数据给服务端了:', JSON.parse(msg));
            client.send('不借');
        });
    });
};

Vue:

组件.vue

<template>
  <button @click="sendData">ws</button>
  <router-view />
</template>

<script setup lang="ts">
  import SocketService from '@/websocket';
  const data = {
    socketServe: SocketService.Instance,
  };
  SocketService.Instance.connect();
  data.socketServe = SocketService.Instance;
  const sendData = () => {
    data.socketServe.send('借我100元');
  };
</script>
websocket.js

export default class SocketService {
    static instance = null;
    static get Instance() {
        if (!this.instance) {
            this.instance = new SocketService();
        }
        return this.instance;
    }
    // 和服务端连接的socket对象
    ws = null;

    // 标识是否连接成功
    connected = false;

    // 重新连接尝试的次数
    connectRetryCount = 0;

    //  连接
    connect() {
        let url = 'ws://localhost:3001';
        this.ws = new WebSocket(url, 'echo-protocol');

        // 连接成功的事件
        this.ws.onopen = () => {
            console.log('连接服务端成功了');
            this.connected = true;
            // 重置重新连接的次数
            this.connectRetryCount = 0;
        };

        // 连接失败的事件
        this.ws.onclose = () => {
            this.connected = false;
            this.connectRetryCount++;
            console.log(`连接服务端失败,已连接${this.connectRetryCount}次`);

            //每3s重新自动连接一次
            setTimeout(() => {
                this.connect();
            }, 3000)
        };

        // 接收服务端发送过来的数据
        this.ws.onmessage = msg => {
            console.log(`从服务端获取到了数据:${msg.data}`);
        };
    }

    // 发送数据的方法
    send(data) {
        if (this.connected) {
            this.ws.send(JSON.stringify(data));
        } else {
            console.log('发送失败')
        }
    }
}

页面列表

ITEM_HTML