2018-11-09 3747
参考资料
在做微信小程序开发的时候需要用到websocket通信,由于小程序没有对actioncable.js的封装,因此需要根据小程序的websocket接口文档进行传递参数的处理。
首先看一下使用actioncable.js模块时的网络数据传输情况
频道订阅
订阅之后返回消息
发送消息
通过以上三张截图可以很明确的看到actioncable.js所做的事情,把rails服务器端需要的数据进行封装,按照固定的格式进行数据传输。
so!为了在小程序中实现同样的功能,只需要按照这个格式对传递的参数进行相应的封装即可。
rails g channel qagame # 创建channel
为了让小程序可以访问到服务器端的数据,需要修改actioncable的配置
config/application.rb
# 添加action_cable配置,关闭跨域检测 config.action_cable.disable_request_forgery_protection = true
# frozen_string_literal: true module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect openid = request.headers["Authorization"] self.current_user = openid end end end
class QagameChannel < ApplicationCable::Channel def subscribed stream_from "qagame_channel" end def unsubscribed # Any cleanup needed when channel is unsubscribed end def join_challenge(data) p "获取客户端数据:#{data}" ActionCable.server.broadcast("qagame_channel", "登录成功") # 返回数据到客户端 end end
const app = getApp() Page({ ... onLoad: function () { // test websocket wx.connectSocket({ url: 'ws://localhost:3000/cable', header: { 'content-type': 'application/json', 'Authorization': '授权信息' }, method: "GET" }); const id = JSON.stringify({ channel: "QagameChannel", id: '这个是订阅参数' }); wx.onSocketOpen(function () { wx.sendSocketMessage({ data: JSON.stringify({ command: "subscribe", identifier: id}), }) }) // 延时发送命令,等待客户端和服务器连接成功 setTimeout(function(){ wx.sendSocketMessage({ data: JSON.stringify({ command: 'message', data: JSON.stringify({ openid: 123, action: 'join_challenge' }), identifier: id }), }) }, 5000) wx.onSocketMessage(function(res){ console.log(res); }) wx.onSocketClose(function(res){ console.log("连接已关闭") console.log(res) }) wx.onSocketError(function(err){ console.log("打开连接失败") console.log(err) }) }, ... })
const formatTime = date => { const year = date.getFullYear() const month = date.getMonth() + 1 const day = date.getDate() const hour = date.getHours() const minute = date.getMinutes() const second = date.getSeconds() return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') } const formatNumber = n => { n = n.toString() return n[1] ? n : '0' + n } // class Actioncable { /** * url ws服务器地址 http://localhost:3000/cable * channel 服务端channel名字如:GameChannel * id 可选参数, * cb 接受返回数据的回调函数 */ constructor(url, channel, id, cb) { wx.connectSocket({ url, header: { 'content-type': 'application/json', 'Authorization': '授权信息' }, method: "GET" }) this.identifier = JSON.stringify({ channel, id }); wx.onSocketOpen(() => { wx.sendSocketMessage({ data: JSON.stringify({ command: "subscribe", identifier: this.identifier }), }) }) wx.onSocketMessage((res) => { console.log(res) // 服务器端返回数据 res = JSON.parse(res.data); if (JSON.stringify(res.identifier) == JSON.stringify(this.identifier)){ if(res.message) { cb(res) } } }) wx.onSocketClose(function (res) { console.log("连接已关闭") console.log(res) }) wx.onSocketError(function (err) { console.log("打开连接失败") console.log(err) }) } /** * 发送消息 * action channel中定义的action名字 * data 传递到action的数据 */ sendMessage(action, data) { var info = {} data.action = action info.command = 'message' info.identifier = this.identifier info.data = JSON.stringify(data) wx.sendSocketMessage({ data: JSON.stringify(info), }) } } module.exports = { formatTime: formatTime, Actioncable }
调用例子
const ws = new Actioncable('ws://localhost:3000/cable', 'QagameChannel', 1211, function(res){ console.log(res); }) setTimeout(() => ws.sendMessage('join_challenge', { openid: 123, nick_name: 'Timer' }), 5000);