简体   繁体   English

基于动态 url 的客户端 JavaScript Socket.io 连接可能吗?

[英]Client-side JavaScript Socket.io connection based on dynamic url possible?

I'm trying out some dynamic options for storing environment variables throughout a distributed app.我正在尝试一些用于在整个分布式应用程序中存储环境变量的动态选项。 I'm struggling with combining a simple Socket.io with chat page with connection based on a URL from a config.json file.我正在努力将简单的 Socket.io 与基于 config.json 文件中的 URL 连接的聊天页面结合起来。 I thought it would be clever on page load to fetch the json file and feed the URL to the socket object.我认为在页面加载时获取 json 文件并将 URL 馈送到套接字 object 会很聪明。 However, I keep running into a chicken and egg issue with the async processing.但是,我一直在异步处理中遇到鸡与蛋的问题。 With what I have right now it starts the connection with the startSocket() function but I would like to have the socket variable available for other functions such as the event listener for the message form.有了我现在所拥有的,它开始与 startSocket() function 的连接,但我希望套接字变量可用于其他功能,例如消息表单的事件侦听器。 Is there a better way to handle the Socket object get me out of this mess?有没有更好的方法来处理 Socket object 让我摆脱困境? Obviously new to web dev.显然是 web 开发人员的新手。

const messageContainer = document.getElementById('message-container')
const messageForm = document.getElementById('send-container')
const messageInput = document.getElementById('message-input')
const name = document.getElementById('chatUserField').getAttribute('data-chatUsername');

fetch('./assets/config.json')
    .then(results => results.json())
    .then(data => {
        startSocket(JSON.stringify(data.SocketIO_URL).replace(/['"]+/g, ''))
    })
    .catch(err=>console.log(err))


function startSocket(url) {
    const socket = io(url)

    appendMessage('you joined')
    socket.emit('new-user', name)

    socket.on('chat-message', data => {
        appendMessage(`${data.name}: ${data.message}`)
    })

    socket.on('user-connected', name => {
        appendMessage(`${name} connected`)
    })

    socket.on('user-disconnected', name => {
        appendMessage(`${name} disconnected`)
    })
}

messageForm.addEventListener('submit', e => {
    e.preventDefault()
    const message = messageInput.value
    appendMessage(`You: ${message}`)
    socket.emit('send-chat-message', message)
    messageInput.value = ''
})

function appendMessage(message) {
    const messageElement = document.createElement('div')
    messageElement.innerText = message
    messageContainer.append(messageElement)
}

Error:错误:

ReferenceError: socket is not defined

There's a few things going on here.这里发生了一些事情。 The reason why you're getting the error, I presume, is not because of the async question you describe—rather it's because in the event listener, you have the following line:我认为您收到错误的原因不是因为您描述的异步问题,而是因为在事件侦听器中,您有以下行:

socket.emit('send-chat-message', message)

However, socket isn't defined here within that function.但是,此处未在 function 中定义socket You defined it in the startSocket function but it's locally scoped , meaning that outside of the code in startSocket , you can't access it.您在startSocket function 中定义了它,但它是 local scoped ,这意味着在startSocket的代码之外,您无法访问它。

Generally you want to add event listeners and all the stuff that depends on the loaded config in the promise .then handler, since JavaScript will then only run that when your config file is loaded (which is what you want.).通常,您希望添加事件侦听器和所有依赖于 promise .then处理程序中加载的配置的东西,因为 JavaScript 只会在您的配置文件加载时运行(这就是您想要的。)。

So I would return the socket object from startSocket :所以我会从startSocket

function startSocket(url) {
    const socket = io(url)

    appendMessage('you joined')
    socket.emit('new-user', name)

    socket.on('chat-message', data => {
        appendMessage(`${data.name}: ${data.message}`)
    })

    socket.on('user-connected', name => {
        appendMessage(`${name} connected`)
    })

    socket.on('user-disconnected', name => {
        appendMessage(`${name} disconnected`)
    })
    return socket;
}

Then I would assign it to a variable in the .then handler.然后我会将它分配给.then处理程序中的一个变量。

fetch('./assets/config.json')
    .then(results => results.json())
    .then(data => {
        // do all processing related to setting stuff up now here
        const mySocket = startSocket(JSON.stringify(data.SocketIO_URL).replace(/['"]+/g, ''));
        // now that we have the socket object, let's set up the event listeners
        messageForm.addEventListener('submit', e => {
            e.preventDefault()
            const message = messageInput.value
            appendMessage(`You: ${message}`)
            mySocket.emit('send-chat-message', message)
            messageInput.value = ''
        })
    })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM