Post

Pass Socket.io as Argument

Harianto van Insulinde

Routes

js
module.exports = ({ Router, io }) => {
    const router = Router()
    /* GET users listing. */
    router
        .get('/', function (req, res, next) {
            res.render('message', { title: 'Message Page' })
        })
        .post('/', (req, res) => {
            io.emit('client-message', { ...req.body, id: 'POST' })
            res.json(req.body)
        })

    return router
}

File: routes/io-message.js

App

js
module.exports = ({ express, app, io }) => {
    const { Router } = express

    app.use('/message', require('./routes/io-message')({ Router, io }))
    
    io.on('connection', socket => {
        console.log('Socket Connect:', { id: socket.id })
        socket.on('disconnect', log => {
            console.log({ id: socket.id, log })
        })

        socket.on('server-message', msg => {
            console.log('message:', { msg })
            io.emit('client-message', { id: socket.id, message: msg })
        })

    })

    return app
}

Snippet: app.js

Server

js
#!/usr/bin/env node

var http = require('http'),
    express = require('express'),
    app = express()

/**
 * Create HTTP server.
 */

var server = http.createServer(app)
var io = require('socket.io')(server)
require('../app')({ express, app, io })

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port)

Snippet: bin/www

View

handlebars
<style rel="stylesheet/less" type="text/less">
    body {
        margin: 0;
        padding: 0;
    }

    .app-tpl {
        height: ~'calc(100vh)';
        overflow-y: auto;
        overflow-x: hidden;
        background-color: rgb(248, 239, 201);
    }

    .messages {
        list-style: none;
        margin: 0;
        padding: 0;

        li {
            &:nth-child(odd) {
                background-color: yellow;
            }
        }
    }
</style>
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/2.7.1/less.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="/socket.io/socket.io.js"></script>

<script type="text/html" id="app-tpl">
    <div class="app-tpl">
           <h1>{{title}}</h1>
           <input v-model="formData.message" placeholder="Message" />
        <div>
            <button @click="onEmit">Emit Message</button>
            <button @click="onPost">Post Message</button>
        </div>
        <ul class="messages">
            <li v-for="msg in messages"><pre v-text="msg" /></li>
        </ul>
    </div>
</script>

<script>
    var socket = io(),
        el = document.currentScript

    const storeMessages = {
            state: Vue.observable({
                messages: []
            }),
            methods: {
                onMessage(message) {
                    this.state.messages.unshift(message)
                }
            }
        },
        App = new Vue({
            template: '#app-tpl',
            data: () => ({
                formData: {
                    message: ''
                }
            }),
            computed: {
                messages() {
                    return storeMessages.state.messages
                }
            },
            methods: {
                onEmit() {
                    const { formData } = this
                    socket.emit('server-message', formData.message)
                    console.log('onEmit:', formData.message)
                    formData.message = ''
                },
                onPost() {
                    const { formData } = this,
                        url = '//localhost:3000/message'
                    console.log('onPost:', formData.message)
                    fetch(url, {
                        method: 'POST',
                        body: JSON.stringify(formData)
                    })
                        .then(res => res.json())
                        .then(console.log.bind(console, 'RESPONSE:'))
                        .catch(console.error.bind(console, 'FAIL - onPost:'))
                    formData.message = ''
                }
            }
        })

    App.$mount(el)

    socket.on(
        'client-message',
        storeMessages.methods.onMessage.bind(storeMessages)
    )
</script>

File: views/message.hbs