Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue-SocketIO callback issues #40

Open
adamlwgriffiths opened this issue Jun 23, 2022 · 1 comment
Open

Vue-SocketIO callback issues #40

adamlwgriffiths opened this issue Jun 23, 2022 · 1 comment

Comments

@adamlwgriffiths
Copy link

adamlwgriffiths commented Jun 23, 2022

The example from #24 demonstrates a console log I'm seeing from Brython, "empty stack".

This seems innocuous in this case (as the callback's "self" parameter is well-formed).

But I'm also seeing it when using vue-socketio, and when using it there. Not only that, but callbacks don't seem to have a "self".

I've tried to make a minimal example below, but appreciate that setting up websockets is a bit non-standard.

This example also demonstrate's vue-socketio's inability to call the mutation functions in the Store object.
I wrote a JS equivalent of this which exhibited no issues, so it's clearly the py<->js interop.

server.py

import os
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.responses import FileResponse
import socketio

def relative_dir(path):
    return os.path.join(os.path.dirname(__file__), path)

app = FastAPI()

app.sio = socketio.AsyncServer(async_mode='asgi')
app.mount('/ws', socketio.ASGIApp(app.sio))

app.mount("/static", StaticFiles(directory=relative_dir('static')), name="static")

@app.get("/")
async def read_index():
    return FileResponse(relative_dir('static/index.html'))

@app.sio.event()
def connect(sid, *args, **kwargs):
    print(f'{sid} connected')

@app.sio.event()
def disconnect(sid, *args, **kwargs):
    print(f'{sid} disconnected')

if __name__ == '__main__':
    import uvicorn
    uvicorn.run("basic_server:app", host="127.0.0.1", port=5000, log_level="info")

index.html

<html>
<head>
    <title>TEST</title>
</head>
<body onload="brython({cache: true, pythonpath: ['/static']})">
    <div id="app"></div>
    <!-- socketio -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/client-dist/socket.io.min.js"></script>
    <!-- vue -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuex.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-router.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-socketio.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/brython.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/brython_stdlib.min.js"></script>

    <script type="text/python">
        from textwrap import dedent
        from browser import window, document, load, html
        from vue import Vue, VueStore, VueComponent, data, computed, mutation
        from vue.decorators.base import VueDecorator, pyjs_bridge

        class Sockets(VueDecorator):
            __key__ = "sockets"
            def __init__(self, fn, name=None):
                self.__id__ = name or fn.__name__
                self.__value__ = pyjs_bridge(fn)

        def sockets(fn):
            if callable(fn):
                return Sockets(fn)
            name = fn
            def inner(fn):
                return Sockets(fn, name)
            return inner

        class Store(VueStore):
            @mutation
            def socket_connect(self):
                print(f'Store.socket_connect()')
            @mutation
            def socket_set_username(self, username):
                print(f'Store.socket_set_username({username})')

        class App(VueComponent):
            template = '<div>Hello</div>'

            @sockets
            def connect(self, *args, **kwargs):
                print(f'App.connect({self}, {args}, {kwargs})')

        store_ = Store()

        Vue.use(window.VueSocketIO.new({
            'debug': True,
            'connection': window.io({
                'path': '/ws/socket.io',
                'transports': ["websocket"],
            }),
            'vuex': {
                'store': store_,
                'actionPrefix': 'socket_',
                'mutationPrefix': 'socket_'
            },
        }))

        App("#app", store=store_)
    </script>
</body>
</html>

Browser console output:

Vue-Socket.io: Received socket.io-client instance 
Vue-Socket.io: Vuex adapter enabled 
Vue-Socket.io: Vuex socket mutations enabled 
Vue-Socket.io: Vuex socket actions enabled 
Vue-Socket.io: Vue-Socket.io plugin enabled 
Vue-Socket.io: #connect subscribe, component: undefined 
vue.min.js:6 Error: callback must be a function
    at t.value (vue-socketio.min.js:14:12327)
    at vue-socketio.min.js:14:9569
    at Array.forEach (<anonymous>)
    at Cn.mounted (vue-socketio.min.js:14:9495)
    at Be (vue.min.js:6:11407)
    at Qt (vue.min.js:6:25438)
    at vue.min.js:6:68707
    at Cn.$mount (vue.min.js:6:68726)
    at Cn.$mount (vue.min.js:6:94030)
    at Cn.t._init (vue.min.js:6:33111)

Vue-Socket.io: Broadcasting: #connect, Data: 
empty stack
App.connect(None, (), {})

There are a few things here:

  1. The "callback must be a function" error.
    Which is being triggered here in vue-socketio.

  2. The callback in App prints 'None' for its value of 'self'

  3. The "empty stack" warning from Brython when using callbacks.

I appreciate vue-socketio isn't your library, but I'm not sure where else to go for assistance.
I've tried poking around inside the vue.py, but I simply don't understand most of what it is attempting to do.

@adamlwgriffiths
Copy link
Author

FYI, I've moved over to native JS vue since I can't overcome these issues, so this isn't a high priority at the moment.
But I'd like to understand how to fix this so I can help improve the bindings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant