參考資料
actioncable
微信小程序
在做微信小程序開發(fā)的時(shí)候需要用到websocket通信川队,由于小程序沒有對(duì)actioncable.js的封裝瞬矩,因此需要根據(jù)小程序的websocket接口文檔進(jìn)行傳遞參數(shù)的處理。
首先看一下使用actioncable.js模塊時(shí)的網(wǎng)絡(luò)數(shù)據(jù)傳輸情況
通過以上三張截圖可以很明確的看到actioncable.js所做的事情,把rails服務(wù)器端需要的數(shù)據(jù)進(jìn)行封裝盲赊,按照固定的格式進(jìn)行數(shù)據(jù)傳輸伸眶。
so惊窖!為了在小程序中實(shí)現(xiàn)同樣的功能,只需要按照這個(gè)格式對(duì)傳遞的參數(shù)進(jìn)行相應(yīng)的封裝即可厘贼。
創(chuàng)建服務(wù)器端代碼
rails g channel qagame # 創(chuàng)建channel
為了讓小程序可以訪問到服務(wù)器端的數(shù)據(jù)界酒,需要修改actioncable的配置
config/application.rb
# 添加action_cable配置,關(guān)閉跨域檢測(cè)
config.action_cable.disable_request_forgery_protection = true
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 "獲取客戶端數(shù)據(jù):#{data}"
ActionCable.server.broadcast("qagame_channel", "登錄成功") # 返回?cái)?shù)據(jù)到客戶端
end
end
客戶端
const app = getApp()
Page({
...
onLoad: function () {
// test websocket
wx.connectSocket({
url: 'ws://localhost:3000/cable',
header: {
'content-type': 'application/json'
},
method: "GET"
});
const id = JSON.stringify({ channel: "QagameChannel", id: '這個(gè)是訂閱參數(shù)' });
wx.onSocketOpen(function () {
wx.sendSocketMessage({
data: JSON.stringify({ command: "subscribe", identifier: id}),
})
})
// 延時(shí)發(fā)送命令嘴秸,等待客戶端和服務(wù)器連接成功
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("連接已關(guān)閉")
console.log(res)
})
wx.onSocketError(function(err){
console.log("打開連接失敗")
console.log(err)
})
},
...
})
附上自己定義的Actioncable
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服務(wù)器地址 http://localhost:3000/cable
* channel 服務(wù)端channel名字如:GameChannel
* id 可選參數(shù),
* cb 接受返回?cái)?shù)據(jù)的回調(diào)函數(shù)
*/
constructor(url, channel, id, cb) {
wx.connectSocket({
url,
header: {
'content-type': 'application/json'
},
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) // 服務(wù)器端返回?cái)?shù)據(jù)
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("連接已關(guān)閉")
console.log(res)
})
wx.onSocketError(function (err) {
console.log("打開連接失敗")
console.log(err)
})
}
/**
* 發(fā)送消息
* action channel中定義的action名字
* data 傳遞到action的數(shù)據(jù)
*/
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
}
調(diào)用例子
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);