Take a note with onPull
event handler. The console.log()
is called before textHistory.push()
, but the console displays textHistory
array with one item inside it, whereas it was an empty array before.
// server.js
import fs from 'node:fs'
import http from 'node:http'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import chokidar from 'chokidar'
import express from 'express'
import { Server } from 'socket.io'
import { createServer as createViteServer } from 'vite'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
let version = 0
async function createServer() {
const app = express()
const server = http.createServer(app)
const io = new Server(server)
const watcher = chokidar.watch('./note.txt', {
ignoreInitial: true
})
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom'
})
app.use(vite.middlewares)
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'index.html'))
})
io.on('connection', (socket) => {
socket.emit('pull', {
version,
data: fs.readFileSync('./note.txt', 'utf8')
})
socket.on('push', (data) => {
fs.writeFileSync('./note.txt', data)
})
watcher.on('change', () => {
version++
socket.emit('pull', {
version,
data: fs.readFileSync('./note.txt', 'utf8')
})
})
})
server.listen(3000)
}
createServer()
// index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width" name="viewport">
</head>
<body>
<textarea
autocapitalize="off"
class="text-editor text-editor--type-push"
cols="20"
id="pushTextEditor"
rows="10"
></textarea>
<textarea
autocapitalize="off"
class="text-editor text-editor--type-pull"
cols="20"
disabled
id="pullTextEditor"
rows="10"
></textarea>
<div class="push-indicator" id="push-indicator"></div>
<button disabled id="push">Push</button>
<button disabled id="pull">Pull</button>
<p id="length"></p>
<script src="/main.js" type="module"></script>
</body>
</html>
// main.js
import eruda from 'eruda'
import { io } from 'socket.io-client'
import './style.css'
eruda.init()
const socket = io()
const pushTextEditorElement = document.getElementById('pushTextEditor')
const pullTextEditorElement = document.getElementById('pullTextEditor')
const pushIndicatorElement = document.getElementById('push-indicator')
const pushElement = document.getElementById('push')
const pullElement = document.getElementById('pull')
const textHistory = []
let initialized = false
let isSync
let pushing = false
let pushTimeout
const pushDelay = 1000
function handleInput(event) {
clearTimeout(pushTimeout)
pushTimeout = setTimeout(() => push(event.target.value), pushDelay)
}
function push(data) {
pushing = true
pushIndicatorElement.classList.add('push-indicator--active')
textHistory.push({
version: textHistory[textHistory.length - 1].version + 1,
data
})
socket.emit('push', data)
}
socket.on('connect', onConnect)
socket.on('pull', onPull)
socket.on('disconnect', onDisconnect)
function onConnect() {
pushTextEditorElement.addEventListener('input', handleInput)
console.log('connected')
}
function onPull(pullObject) {
/* bug here */
console.log(textHistory)
if (!initialized) {
initialized = true
isSync = true
textHistory.push(pullObject)
pushTextEditorElement.value = pullObject.data
pullTextEditorElement.value = pullObject.data
}
}
function onDisconnect() {
pushTextEditorElement.removeEventListener('input', handleInput)
}
Here is the project code socket.io-playground
However, if I remove the console.log()
and use other display method like writing into the dom with document.getElementById('...').textContent = textHistory.length
, it displays 0
!