Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >微信小程序中websocket的运用

微信小程序中websocket的运用

作者头像
越陌度阡
发布于 2020-11-26 06:51:45
发布于 2020-11-26 06:51:45
1.4K00
代码可运行
举报
运行总次数:0
代码可运行

近期在开发一个类似于小年糕的小程序,当用户在合成影集后会立马跳到个人中心的影集列表,但是立刻跳过去,服务端并没有马上制作完成,所以会有个“影集正在制作中”的提示,为了避免用户退出页面重新请求查看影集是否制作完成,决定前后端通信采用websocket通信的方式,当有影集制作完成时,服务端可实时向用户推送消息。

websocket在实现时需要注意以下几点:

1. 微信小程序同时只能有一个 WebSocket 连接,如果当前已存在一个 WebSocket 连接,会自动关闭该连接,并重新创建一个 WebSocket 连接。

2. WebSocket 链接默认和最大超时时间都是 60s,超过了这个时间会自动断开,所以要设置一个心跳链接。

3. 页面在卸载时要关闭socket的链接。

以下是websocket连接及心跳的实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 域名地址(项目实地址)
const Host = 'wss://xxxx:0000';

// Socket连接成功
var socketOpen = false;
// Socket关闭
var socketClose = false;
// 消息队列
var socketMsgQueue = [];

// 判断心跳变量
var heart = null;
// 心跳失败次数
var heartBeatFailCount = 0;
// 终止心跳
var heartBeatTimeout = null;
// 终止重连
var connectSocketTimeout = null;

var webSocket = {
    // 连接Socket
    connectSocket:function(options) {
        wx.showLoading({
            title: '正在请求中',
            mask: true,
        });
        socketOpen = false;
        socketClose = false;
        socketMsgQueue = [];
        wx.connectSocket({
            url:Host,
            success:function(res) {
                if (options) {
                    options.success && options.success(res);
                }
            },
            fail:function(res) {
                if (options) {
                    options.fail && options.fail(res);
                }
            }
        })
    },
    // 发送消息
    sendSocketMessage:function(options) {
        if (socketOpen) {
            wx.sendSocketMessage({
                data: options.msg,
                success: function(res) {
                    if (options) {
                        options.success && options.success(res);
                    }
                },
                fail: function(res) {
                    if (options) {
                        options.fail && options.fail(res);
                    }
                }
            })
        } else {
            socketMsgQueue.push(options.msg)
        }
    },
    // 关闭Socket
    closeSocket: function(options) {
        if (connectSocketTimeout) {
            clearTimeout(connectSocketTimeout);
            connectSocketTimeout = null;
        };
        socketClose = true;
        this.stopHeartBeat();
        wx.closeSocket({
            success: function(res) {
                if (options) {
                    options.success && options.success(res);
                }
            },
            fail: function(res) {
                if (options) {
                    options.fail && options.fail(res);
                }
            }
        })
    },
    // 收到消息
    onSocketMessageCallback: function(msg) {},

    // 开始心跳
    startHeartBeat: function() {
        heart = true;
        this.heartBeat();
    },

    // 正在心跳
    heartBeat: function() {
        var that = this;
        if (!heart) {
            return;
        };
        that.sendSocketMessage({
            msg: JSON.stringify({
                // 与后端约定,传点消息,保持链接
                "msg_type": "heart"
            }),
            success: function(res) {
                if (heart) {
                    heartBeatTimeout = setTimeout(() => {
                        that.heartBeat();
                    }, 7000);
                }
            },
            fail: function(res) {
                if (heartBeatFailCount > 2) {
                    that.connectSocket();
                };
                if (heart) {
                    heartBeatTimeout = setTimeout(() => {
                        that.heartBeat();
                    }, 7000);
                };
                heartBeatFailCount++;
            },
        });
    },

    // 结束心跳
    stopHeartBeat: function() {
        heart = false;
        if (heartBeatTimeout) {
            clearTimeout(heartBeatTimeout);
            heartBeatTimeout = null;
        };
        if (connectSocketTimeout) {
            clearTimeout(connectSocketTimeout);
            connectSocketTimeout = null;
        }
    }
};

// 监听WebSocket打开连接
wx.onSocketOpen(function(res) {
    wx.hideLoading();
    // 如果已经关闭socket
    if (socketClose) {
        webSocket.closeSocket();
    } else {
        socketOpen = true
        for (var i = 0; i < socketMsgQueue.length; i++) {
            webSocket.sendSocketMessage(socketMsgQueue[i])
        };
        socketMsgQueue = []
        webSocket.startHeartBeat();
    }
});

// 监听WebSocket错误
wx.onSocketError(function(res) {
    console.log('WebSocket连接打开失败,请检查!', res);
});
// 监听WebSocket接受到服务器的消息
wx.onSocketMessage(function(res) {
    webSocket.onSocketMessageCallback(res.data);
});

// 监听WebSocket关闭连接后马上重连
wx.onSocketClose(function(res) {
    if (!socketClose) {
        clearTimeout(connectSocketTimeout);
        connectSocketTimeout = setTimeout(() => {
            webSocket.connectSocket();
        }, 3000);
    }
});

module.exports = webSocket;

以下是页面中的使用,其中在onSocketMessageCallback里面会有消息回调。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const WebSocket = require('../../public/websocket.js');

Page({
    // 页面加载
    onLoad: function(options) {
        // 创建连接
        WebSocket.connectSocket();
        // 设置接收消息回调
        WebSocket.onSocketMessageCallback = this.onSocketMessageCallback;
    },

    // Socket收到的信息
    onSocketMessageCallback: function(res) {
        console.log(res);
    },
    // 页面销毁时关闭连接
    onUnload: function(options) {
        WebSocket.closeSocket();
    },
})
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
redis面试总结
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
三哥
2018/08/20
8750
面试总结-链接
https://blog.csdn.net/CCUTwangning/article/details/70153589 天下无难试之Redis面试题刁难大全 https://blog.csdn.net/g0_hw/article/details/79360073
小二三不乌
2018/08/02
3070
redis和memcached的优缺点及区别
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
黄啊码
2020/05/29
1.6K0
如何保证redis里都是热点数据呢&&Memcache与Redis的区别
redis 提供 6种数据淘汰策略: 大体上:是可以从设置过期时间数组集里挑选最少使用的或者将要过期的或者任意数据淘汰,也可以禁止淘汰 具体的:
名字是乱打的
2021/12/22
5440
如何保证redis里都是热点数据呢&&Memcache与Redis的区别
Redis面试题(一): Redis到底是多线程还是单线程?
Q: 那这样子,在读取socket1的数据时,如果其它socket有数据来,那么也要等到socket1读取完了才能继续读取其它socket的数据吧。那不是也阻塞住了吗?而且读取到的数据也要开启线程处理吧,那这和多线程IO有什么区别呢? A: 1.CPU本来就是线性的不论什么都需要顺序处理并行只能是多核CPU 2.io多路复用本来就是用来解决对多个I/O监听时,一个I/O阻塞影响其他I/O的问题,跟多线程没关系. 3.跟多线程相比较,线程切换需要切换到内核进行线程切换,需要消耗时间和资源.而I/O多路复用不需要切换线/进程,效率相对较高,特别是对高并发的应用nginx就是用I/O多路复用,故而性能极佳.但多线程编程逻辑和处理上比I/O多路复用简单.而I/O多路复用处理起来较为复杂.
全栈程序员站长
2022/08/18
4580
Redis面试题(一): Redis到底是多线程还是单线程?
Redis的基础介绍与安装使用步骤
Redis的基础介绍与安装使用步骤:https://www.jianshu.com/p/2a23257af57b Redis的基础数据结构与使用:https://www.jianshu.com/p/c95c8450c5b6 Redis核心原理:https://www.jianshu.com/p/4e6b7809e10a Redis 5 之后版本的高可用集群搭建:https://www.jianshu.com/p/8045b92fafb2 Redis 5 版本的高可用集群的水平扩展:https://www.jianshu.com/p/6355d0827aea Redis 5 集群选举原理分析:https://www.jianshu.com/p/e6894713a6d5 Redis 5 通信协议解析以及手写一个Jedis客户端:https://www.jianshu.com/p/575544f68615
zoro
2019/04/11
7080
Redis的基础介绍与安装使用步骤
常见的Redis面试题及分布式集群讲解
作者:蘑菇先生 出处:http://www.cnblogs.com/mushroom/ 1. 使用Redis有哪些好处? (1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1) (2) 支持丰富数据类型,支持string,list,set,sorted set,hash (3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行 (4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
Tanyboye
2018/07/02
2K0
redis面试题
1、Redis的特点? Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万次读写操作,是已知性能最快的Key-Value DB。
用户9131103
2023/07/17
1340
【162期】一些Redis面试题及分布式集群面试考点整理
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
良月柒
2021/03/26
5800
Redis和Memcache区别,优缺点对比
个人总结一下,有持久化需求或者对数据结构和处理有高级要求的应用,选择redis,其他简单的key/value存储,选择memcache。
Cheng_Blog
2022/02/25
3.9K0
《redis 设计与实现》--总结
Redis自己构建了简单动态字符串(Simple Dynamic String,SDS)来作为默认的字符串表示。 SDS的构造如下:
小二三不乌
2018/08/07
8460
《redis 设计与实现》--总结
redis组件
redis-server:服务器端工具 redis-cli:客户端工具 redis-benchmark:redis性能压力测试工具 redis-check-dump(rdb格式) & redis-check-aof(aof格式):检测持久化存储RDB/AOF的文件格式是否错误,以及发现错误进行修复 redis-shutdown:用于关闭redis redis-sentinel:用于实现redis主从切换的工具 ```
玖柒的小窝
2021/09/19
3750
非常值得一看的35个Redis面试题总结(一)
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。
互扯程序
2019/07/10
9470
Redis详解 单线程 基于内存设计 主从 持久化 与 memcached区别 及常见问题
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。
大鹅
2021/06/16
5250
Redis最常见面试问题
来 源:cnblogs.com/Survivalist/p/8119891.html
JavaFish
2019/11/01
4220
网络上收集的有关 Redis 方面的面试题
假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来 使用keys指令可以扫出指定模式的key列表 ### 对应的问题 因为redis 是单线程 所以一次性操作大量的数据 可能会导致业务出现卡顿 ### 解决办法 这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长. Redis有哪些数据结构? 字符串String、字典H
风清醉
2019/12/18
4800
Redis面试题总结
参考 https://blog.csdn.net/zdp072/article/details/50991116 https://blog.csdn.net/qq_34337272/article/details/80012284#commentBox
凯哥Java
2022/12/16
3170
Redis面试题总结
从阿里、腾讯的面试真题中总结了这11个Redis高频面试题
现在大家的工作生活基本已经是回归正轨了,最近也是迎来了跳槽面试季,有些人已经拿到了一两个offer了。
程序员追风
2020/04/02
7670
从阿里、腾讯的面试真题中总结了这11个Redis高频面试题
2021最新版 史上最全的50个Redis面试题(含答案)
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。
猫头虎
2024/04/07
2350
2021最新版 史上最全的50个Redis面试题(含答案)
值得一看的35个Redis面试题总结
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。
民工哥
2020/09/16
8140
相关推荐
redis面试总结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验