2017-01-18 5 views
0

모든 게시물을 서버 (phoenix 프레임 워크 + PostgreSQL)에서 가져 오는 작은 앱 (js)을 프로그래밍했습니다. 응용 프로그램은 작동하고 있지만, API의 N 번째 호출에서, 나는 얻을 대신 의 응답N :피닉스 채널 : 모든 요청마다 이전보다 더 많은 답장을받습니다.

입니다
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 './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 
:

import {Socket} from 'phoenix' 
let socket = new Socket('/socket', {params: {token: window.userToken}}) 
socket.connect() 
export default socket 

채널을 관리 할 수있는 몇 가지 코드

데이터 가져 오기 :

[...] 
    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

당신이 fetchData()를 호출 할 때마다, 당신은으로 새로운 리스너를 추가하는 것 같다 c.on('getAll', ...) 전화. 따라서 모든 수신 메시지에 대해 점점 많은 양의 청취자가 실행되므로 많은 메시지를받은 것처럼 보입니다.

브라우저의 개발자 도구로이를 확인할 수 있습니다. 적어도 Chromium 기반 브라우저는 WebSocket 트래픽을 검사하여받은 메시지가 하나만 있음을 확인합니다.