WebSocket在web端和小程序端的坑!

如题再使用webSocket的过程中遇到了一些很让人头痛的坑

  • 关于WebSocket,Stomp over WebSocket相关的定义就不在赘述了
    • 第一次尝试
    • 第二次尝试

关于WebSocket,Stomp over WebSocket相关的定义就不在赘述了

我先是使用的Stomp over WebSocket实现了一次消息推送。然后心血来潮想要在uni-app上面也实现一次。(uni-app是基于Vue.JS的)结果就很自然的出问题了。下面整理一下在uniapp整合WebSocket中遇到的bug

第一次尝试

因为我没有什么小程序的底子,我先想当然的像web开发一样去写。先引入stomJS和sockJS包,然后用new Socket(url)的方式去实例化SockJs,然后通过创建StompClient去连接订阅。


	connect: function(userId,txtNumber, successCallback) {
		   var socket = new SockJS(sprintf("http://%s:8081/socket", serverIp));//实例化sockJS
		   page.stompClient = Stomp.over(socket);//实例化STOMP

			var headers = {
        	    "passcode" : "343",
        	    "login": userId,
				"chatNumber":txtNumber
			};


			//stompClient.debug = null;

			page.stompClient.connect(headers, function(response) {//连接客户端
          		successCallback(response);//;连接成功时

			}, function(disconnectedMessage){//连接失败时
				console.log(disconnectedMessage);
			});
	},

	bindEvent: function() {

	
		$("#btnJoin").on("click", function() {
			var userId = $("#txtName").val();
            var txtNumber = $("#txtNumber").val();
			page.connect(userId, txtNumber,function(response){

				$(".loginDiv").hide();
				$(".container").show();

				var users = JSON.parse(response.body);
				$.each(users, function(index, user){
					page.renderUser(user);
				});

				// emphasize current user
				page.$userList.find("#" + userId).find("h5").css("font-weight", "bold").css("font-style", "italic")

				var channel = "/topic/chat".concat(ChannelType.NEW_MESSAGE).concat("/"+txtNumber);
				page.stompClient.subscribe(channel, function(response){
                	var msg = JSON.parse(response.body);
                	page.renderMessage(msg)
            	});


				var channel = "/topic/chat".concat(ChannelType.NEW_USER).concat("/"+txtNumber);
				page.stompClient.subscribe(channel, function(response){
                	var user = JSON.parse(response.body);
                	page.renderUser(user);
                	console.log(user);
            	});

				var channel = "/topic/chat".concat(ChannelType.OFFLINE).concat("/"+txtNumber);
				page.stompClient.subscribe(channel, function(response){
                	var user = JSON.parse(response.body);
                	page.removeUser(user);
            	});
			})
		});




		$("#btnSend").on("click", function(){
            var txtNumber = $("#txtNumber").val();
			var $txtMessage = $("#txtMessage");
			var msg = $txtMessage.val();
			$txtMessage.val("");
			page.stompClient.send("/app/chat", {}, JSON.stringify({"message": msg,"chatNumber":txtNumber}));
		});
	},

	renderMessage: function(msg) {
		var $msgModel = page.$msgModel.clone();
    	$msgModel.find(".lblMsg").text(msg.message);
    	$msgModel.find(".lblUser").text(msg.sender);
    	page.$msgList.append($msgModel);
	},

	renderUser: function(user) {
		var $userModel = page.$userModel.clone();
		$userModel.prop("id", user.userId);
		$userModel.find(".lblUser").text(user.userId);
    	page.$userList.append($userModel);
	},

	removeUser: function(user) {
		page.$userList.find("#" + user.userId).remove();
	}
};

$(document).ready(function(){
	page.init();

	window.onbeforeunload = function (event) {

		// demonstrate before closing browser,
		// no need to call this, disconnect is called when tab/browser is close
		if(page.stompClient != null) {
			page.stompClient.disconnect();
		}
	};

})

这里只展示了部分关键代码。H5是连接没有任何问题,但换到uni-app的时候问题就来了,sockjs.js里面用了一点操作DOM元素的方法,比如document.getElementsByTagName,uni-app是解析不了的,原生的微信小程序好像也解析不了?这我没有去试验过。反正H5的方式算是崩了。

第二次尝试

这次放弃了使用外部的js,采用原生的uni.connectSocket()的方式创建连接。

SocketTask = uni.connectSocket({
				//192.28.182.150
				url: 'http://192.28.182.150:8081/socket',
				//url: 'ws://localhost:8081/socket',
				data: 'data',
				header: {
					'content-type': 'application/json',
					"passcode": "343",
					"login": 1,
					"chatNumber": 1
				},
				method: 'post',
				success: function(res) {
					console.log('WebSocket连接创建', res)
				},
				fail: function(err) {
					uni.showToast({
						title: '网络异常!',
					})
					console.log(err)
				},
			})

代码中显示的就很清楚了,uni-app连接websocket的时候要是用ws或者wss,相当于http和https。
不然就会报无效的url这种异常。但是这个时候还是会抛异常。
Error during WebSocket handshake: Unexpected response code: 200
网上查了很多博客帖子大多说是拦截器的问题。但是检查了我的服务端代码,发现是没有问题的,最后找到了问题的关键。先贴一下服务端配置

@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/socket").setAllowedOrigins("*")
			.addInterceptors(new ConnectionInterceptor()).withSockJS();
	}

我服务端是开启了sockjs模式的。将此处的withSockJS()去除,就可以通过原生方式连接了,因为soketjs在浏览器不支持wobsoket请求是会自动切换为http请求轮训方式。结果就挂了。以前一直做后端,第一次玩这个东西踩了很多坑。好在最后都一一解决了。感谢度娘

你可能感兴趣的:(日常解决bug篇)