Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9016

Node.js: Server Sent Events のサンプル (画像表示)

$
0
0
こちらのプログラムを簡単にしたサンプルを作成しました。 simonprickett/server-sent-events-demo 次のような出力を出すようにします。 サーバー フォルダー構成 $ tree . ├── package.json └── server.js server.js // --------------------------------------------------------------- // server/server.js // // May/20/2021 // --------------------------------------------------------------- const http = require('http') const PORT = process.env.PORT || 5000 const memes = [ 'https://ekzemplaro.org/tmp/images/a001.jpg', 'https://ekzemplaro.org/tmp/images/a002.jpg', 'https://ekzemplaro.org/tmp/images/a003.jpg', 'https://ekzemplaro.org/tmp/images/a004.jpg', 'https://ekzemplaro.org/tmp/images/a005.jpg', 'https://ekzemplaro.org/tmp/images/a006.jpg', 'https://ekzemplaro.org/tmp/images/a007.jpg' ] // --------------------------------------------------------------- function getRandomIndex(low, high) { const min = Math.ceil(low) const max = Math.floor(high) return Math.floor(Math.random() * (max - min + 1)) + min } // --------------------------------------------------------------- function createRandomMemeMessage() { console.log('Sending meme message.') return (`event: meme\ndata:${memes[getRandomIndex(0, memes.length - 1)]}\n\n\n`) } // --------------------------------------------------------------- function createRandomNamedEvents(request, response) { response.writeHead(200, { Connection: 'keep-alive', 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' }) let eventsSent = 1 const interval = setInterval(() => { if (eventsSent === 31) { clearInterval(interval) console.log('Sent 30 events, stopping.') response.write('id: -1\ndata:\n\n\n') response.end() return } response.write(`id: ${eventsSent < 10 ? '0' : ''}${eventsSent}\n`) response.write(createRandomMemeMessage()) eventsSent += 1 }, 3000) request.on('close', () => { clearInterval(interval) response.end() console.log('Stopped sending events as client closed the connection.') }) } http.createServer((request, response) => { response.setHeader('Access-Control-Allow-Origin', '*') response.setHeader('Access-Control-Request-Method', '*') response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET') response.setHeader('Access-Control-Allow-Headers', '*') if (request.method === 'OPTIONS') { response.writeHead(200) response.end() return } switch (request.url) { case '/randomNamedEvents': createRandomNamedEvents(request, response) break default: // Unknown URL response.writeHead(404) response.end() } }).listen(PORT) console.log(`server-sent-events-demo server running on port ${PORT}`) // --------------------------------------------------------------- package.json { "name": "sse-server-demo", "version": "0.0.1", "description": "Server Sent Events Demonstration Server", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js" }, "repository": { "type": "git", "url": "git+https://github.com/simonprickett/server-sent-events-demo.git" }, "keywords": [ "server-sent-events", "node" ], "author": "Simon Prickett", "license": "MIT", "bugs": { "url": "https://github.com/simonprickett/server-sent-events-demo/issues" }, "homepage": "https://github.com/simonprickett/server-sent-events-demo#readme" } サーバーの起動 npm install npm start クライアント 以下のファイルを、Nginx または Apache2 の配下に置きます。 次のようにサーバーを動かす手もあります。 python -m http.server 8000 フォルダー構成 $ tree . ├── css │   └── app.css ├── index.html └── js └── app.js index.html <! DOCTYPE html> <html> <head> <meta charset="utf-8" <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Server Sent Events Demo</title> <link rel="stylesheet" href="css/app.css"> <script src="js/app.js"></script> </head> <body> <div id="browserSupport" class="browserSupport"> </div> <div id="meme" class="box memes"> Meme Image Events </div> <div id="eventLog" class="rectangle eventLog"> <!-- Event Log will go here --> </div> <hr /> May/20/2021 AM 06:57<br /> </body> </html> js/app.js // --------------------------------------------------------------- // client/js/app.js // // May/20/2021 // --------------------------------------------------------------- const app = { updateEventsReceived: (event) => { document.getElementById('eventLog').insertAdjacentHTML('afterbegin', `<br>${event.lastEventId}: (${event.type}) ${event.data}`); }, resetStartButton: () => { document.getElementById('startEvents').value = 'Start Events'; }, startEvents: () => { app.eventSource = new EventSource('http://localhost:5000/randomNamedEvents'); app.eventSource.onmessage = (e) => { console.log(e); if (e.lastEventId === '-1') { app.eventSource.close(); document.getElementById('eventLog').insertAdjacentHTML('afterbegin', '<br>End of event stream from server.'); app.resetStartButton(); } }; app.eventSource.addEventListener('meme', (e) => { console.log(e); document.getElementById('meme').innerHTML = `<img class="memeImage" src="${e.data}">`; app.updateEventsReceived(e); }); app.eventSource.addEventListener('error', (e) => { console.log('got an error'); console.log(e); app.resetStartButton(); }); } }; document.addEventListener('DOMContentLoaded', () => { const browserSupportElem = document.getElementById('browserSupport'); if (!! window.EventSource) { browserSupportElem.innerHTML = '<input type="submit" class="startEvents" id="startEvents" value="Start Events">'; // browserSupportElem.innerHTML = 'This browser supports <tt>EventSource</tt>! <input type="submit" class="startEvents" id="startEvents" value="Start Events">'; document.getElementById('startEvents').addEventListener('click', function(event) { if (this.value === 'Start Events') { this.value = 'Stop Events'; app.startEvents(); } else { app.eventSource.close(); document.getElementById('eventLog').insertAdjacentHTML('afterbegin', '<br>Event stream closed by browser.'); app.resetStartButton(); } }); } else { browserSupportElem.innerHTML = 'This browser does not support <tt>EventSource</tt> :('; browserSupportElem.classList.add('unsupportedBrowser'); } }); // --------------------------------------------------------------- css/app.css /* client/css/app.css */ html { background-color: #000000; color: #FFFFFF; } a { color: #EEEE00; text-decoration: none; } .header { text-align: center; font-size: 3.0em; margin-top: 15px; } .container { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; margin: auto; max-width: 1200px; width: 90%; } .browserSupport { width: 80%; height: 60px; max-width: 960px; text-align: center; border-radius: 5px; border-color: #FFFFFF; border-width: 1px; background-color: #00BB00; color: #FFFFFF; font-size: 2em; line-height: 60px; margin-bottom: 30px; margin-top: 30px; margin-left: auto; margin-right: auto; } .unsupportedBrowser { background-color: #EE0000; } .box { width: 180px; height: 180px; border-radius: 5px; border-style: solid; border-color: #FFFFFF; border-width: 1px; margin: .5em; padding: 1em; text-align: center; font-size: 2em; color: #FFFFFF; } .startEvents { border-color: #FFFFFF; border-radius: 5px; border-width: 1px; border-style: solid; padding: 5px; font-size: 0.75em; float: right; margin-top: 10px; margin-right: 20px; } .startEvents:active { background-color: #888888; } .memes { background-color: #FFEE00; } .memeImage { width: 100%; height: 100%; } .eventLog { font-family: monospace; font-size: 1.25em; height: 150px; width: 600px; border-radius: 5px; border-style: solid; border-color: #FFFFFF; border-width: 1px; margin: 20px; overflow-y: scroll; overflow-x: hidden; padding: 5px; }

Viewing all articles
Browse latest Browse all 9016

Trending Articles