凤凰卫视频道:每次请求,都会收到比以前更多的回复

时间:2017-01-18 07:43:30

标签: websocket elixir phoenix-framework channel

我编写了一个小应用程序(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>

1 个答案:

答案 0 :(得分:1)

似乎每次拨打fetchData()时,都会添加一个带有c.on('getAll', ...)电话的新听众。因此,对于每个收到的消息,您都会运行越来越多的侦听器,这就是为什么看起来您收到了很多消息。

您可以使用浏览器的开发者工具进行检查 - 至少基于Chromium的浏览器允许您检查WebSocket流量,以确定只有一条收到的消息。