我编写了一个小应用程序(js),它可以从服务器(phoenix framework + PostgreSQL)获取博客的所有帖子。该应用程序正在运行,但在API的 n 调用中,我得到 n 回复而不是 1 :
Joined successfully app.js:18747:10
client getAll call app.js:18698:8
client getAll reply, Object { posts: Array[3] } app.js:18694:10
client getAll call app.js:18698:8
client getAll reply, Object { posts: Array[3] } app.js:18694:10
client getAll reply, Object { posts: Array[3] } app.js:18694:10
client getAll call app.js:18698:8
client getAll reply, Object { posts: Array[3] } app.js:18694:10
client getAll reply, Object { posts: Array[3] } app.js:18694:10
client getAll reply, Object { posts: Array[3] }
就是:在第3次通话时,我得到3回复,而不是1。
这里有文件:user_socket.ex
:
defmodule Proto1.UserSocket do
use Phoenix.Socket, Phoenix.LongPoll
channel "blog", Proto1.BlogChannel
transport :websocket, Phoenix.Transports.WebSocket
transport :longpoll, Phoenix.Transports.LongPoll
def connect(_params, socket) do
{:ok, socket}
end
def id(_socket), do: nil
end
blog_channel.ex
defmodule Proto1.BlogChannel do
use Proto1.Web, :channel
def join("blog", _message, socket) do
{:ok, socket }
end
def handle_in("getAll", params, socket) do
IO.puts "Proto1.BlogChannel.handle_in \"all\" called"
posts = Repo.all(Proto1.Post)
push socket, "getAll", %{posts: for p <- posts do %{title: p.title, body: p.body} end }
{:noreply, socket}
end
end
在客户端(vue.js 2):端点:
defmodule Proto1.Endpoint do
use Phoenix.Endpoint, otp_app: :proto1
socket "/socket", Proto1.UserSocket
套接字:
import {Socket} from 'phoenix'
let socket = new Socket('/socket', {params: {token: window.userToken}})
socket.connect()
export default socket
管理频道的一些代码:
import socket from './socket'
class Blog {
// in the future the construcor will have a single parameter with the
// id of the blog, now we hava a single blog
constructor (blogId) {
this._blogId = blogId
this._channel = socket.channel('blog')
this.join()
this.initOn()
}
join () {
this._channel.join()
.receive('ok', resp => { console.log('Joined successfully') })
.receive('error', resp => { console.log('Unable to join') })
}
initOn () {
this._channel.on('all', payload => {
console.log('payload: ', payload)
})
}
getChannel () {
return this._channel
}
}
let BlogFactory = {
blogs: new Map(),
getBlog: function (blogId = 'default') {
if (this.blogs[blogId] === undefined) {
this.blogs[blogId] = new Blog(blogId)
}
return this.blogs[blogId]
}
}
export default BlogFactory
数据提取:
[...]
methods: {
fetchData () {
this.error = this.posts = null
this.loading = true
var blog = BlogFactory.getBlog()
var c = blog.getChannel()
c.on('getAll', payload => {
console.log('client getAll reply, ', payload)
this.loading = false
this.posts = payload.posts
})
console.log('client getAll call')
c.push('getAll')
}
}
[...]
在@Nicd回答后更改了客户端程序(以下代码有效!):
<script>
// import BlogFactory from '../blog'
import socket from '../socket'
export default {
name: 'blog',
data () {
return {
loading: false,
posts: null,
error: null
}
},
created () {
this.channel = socket.channel('blog')
this.channel.join()
.receive('ok', resp => { console.log('Joined successfully') })
.receive('error', resp => { console.log('Unable to join') })
this.channel.on('getAll', payload => {
console.log('client getAll reply, ', payload)
this.loading = false
this.posts = payload.posts
})
this.fetchData()
},
methods: {
fetchData () {
this.error = this.posts = null
this.loading = true
console.log('client getAll call')
this.channel.push('getAll')
}
}
}
</script>
答案 0 :(得分:1)
似乎每次拨打fetchData()
时,都会添加一个带有c.on('getAll', ...)
电话的新听众。因此,对于每个收到的消息,您都会运行越来越多的侦听器,这就是为什么看起来您收到了很多消息。
您可以使用浏览器的开发者工具进行检查 - 至少基于Chromium的浏览器允许您检查WebSocket流量,以确定只有一条收到的消息。