お世話になっております。
node.jsのsocket.ioを使用し、WEBアプリを実装しようと考えおります。
あるイベントを受け取ったときに1度だけ処理を実現させたいです。
そこで、フラグで処理を管理しようとしております。
ただ、イベントがほぼ同時に2回以上起こった場合、フラグを操作する前にそれらの処理がすり抜けてしまい、処理が2度以上行われることがあるのではないかと思い、質問させていただきました。
そこで、お伺いしたいのですが、
- イベントがほぼ同時に2回以上起こった場合、処理が2度以上行われることがあるかどうか。
- 上記のことが起こる場合、回避策があるかどうか
をご教授いただけると幸いです。
大変お手数ですがよろしくお願いいたします。
node
1'use strict'; 2 3// モジュール 4const express = require( 'express' ); 5const http = require( 'http' ); 6const socketIO = require( 'socket.io' ); 7 8// オブジェクト 9const app = express(); 10const server = http.Server( app ); 11const io = socketIO( server ); 12 13// 定数 14const PORT = process.env.PORT || 8080; 15 16/* 処理を管理するためのフラグ */ 17let onceFlag = true; 18 19io.on( 20 socket.on( 21 'once', 22 () => 23 { 24 if(onceFlag) { 25 onceFlag = false; 26 /* ここに一度しか行わせたくない処理を書く */ 27 } 28 } ); 29);
試したソースコードを追記いたします。
最初に記述したソースコードがエラーになってしまい、申し訳ございませんでした。
node
1'use strict'; 2 3// モジュール 4const express = require( 'express' ); 5const http = require( 'http' ); 6const socketIO = require( 'socket.io' ); 7 8// オブジェクト 9const app = express(); 10const server = http.Server( app ); 11const io = socketIO( server ); 12 13// 定数 14const PORT = process.env.PORT || 8080; 15const SYSTEMNICKNAME = '**system**'; 16 17// 関数 18// 数字を2桁の文字列に変換 19const toDoubleDigitString = 20 ( num ) => 21 { 22 return ( "0" + num ).slice( -2 ); // slice( -2 )で後ろから2文字取り出す。 23 }; 24 25// 時刻文字列の作成(書式は「YY/DD/MM hh:mm ss」) 26const makeTimeString = 27 ( time ) => 28 { 29 return toDoubleDigitString( time.getFullYear() ) + '/' + toDoubleDigitString( time.getMonth() + 1 ) + '/' + toDoubleDigitString( time.getDate() ) 30 + ' ' + toDoubleDigitString( time.getHours() ) + ':' + toDoubleDigitString( time.getMinutes() ) + ' ' + toDoubleDigitString( time.getSeconds() ); 31 } 32 33// グローバル変数 34let iCountUser = 0; // ユーザー数 35 36/* 処理を管理するためのフラグ */ 37let onceFlag = true; // ボタンの状態 38 39// 接続時の処理 40// ・サーバーとクライアントの接続が確立すると、 41// サーバー側で、'connection'イベント 42// クライアント側で、'connect'イベントが発生する 43io.on( 44 'connection', 45 ( socket ) => 46 { 47 console.log( 'connection' ); 48 49 let strNickname = ''; // コネクションごとで固有のニックネーム。イベントをまたいで使用される。 50 51 // 切断時の処理 52 // ・クライアントが切断したら、サーバー側では'disconnect'イベントが発生する 53 socket.on( 54 'disconnect', 55 () => 56 { 57 console.log( 'disconnect' ); 58 59 if( strNickname ) 60 { 61 // ユーザー数の更新 62 iCountUser--; 63 64 // メッセージオブジェクトに現在時刻を追加 65 const strNow = makeTimeString( new Date() ); 66 67 // システムメッセージの作成 68 const objMessage = { 69 strNickname: SYSTEMNICKNAME, 70 strMessage: strNickname + ' left.' + " there are " + iCountUser + " participants", 71 strDate: strNow 72 } 73 74 // 送信元含む全員に送信 75 io.emit( 'spread message', objMessage ); 76 } 77 } ); 78 79 // 入室時の処理 80 // ・クライアント側のメッセージ送信時の「socket.emit( 'join', strNickname );」に対する処理 81 socket.on( 82 'join', 83 ( strNickname_ ) => 84 { 85 console.log( 'joined :', strNickname_ ); 86 87 // コネクションごとで固有のニックネームに設定 88 strNickname = strNickname_; 89 90 // ユーザー数の更新 91 iCountUser++; 92 93 // メッセージオブジェクトに現在時刻を追加 94 const strNow = makeTimeString( new Date() ); 95 96 // システムメッセージの作成 97 const objMessage = { 98 strNickname: SYSTEMNICKNAME, 99 strMessage: strNickname + ' joined.' + " there are " + iCountUser + " participants", 100 strDate: strNow 101 } 102 103 // 送信元含む全員に送信 104 io.emit( 'spread message', objMessage ); 105 } ); 106 107 // 新しいメッセージ受信時の処理 108 // ・クライアント側のメッセージ送信時の「socket.emit( 'new message', $( '#input_message' ).val() );」に対する処理 109 socket.on( 110 'new message', 111 ( strMessage ) => 112 { 113 console.log( 'new message', strMessage ); 114 115 // 現在時刻の文字列の作成 116 const strNow = makeTimeString( new Date() ); 117 118 // メッセージオブジェクトの作成 119 const objMessage = { 120 strNickname: socket.id, 121 strMessage: strMessage, 122 strDate: strNow 123 } 124 125 // 送信元含む全員に送信 126 //io.emit( 'spread message', strMessage ); 127 io.emit( 'spread message', objMessage ); 128 } ); 129 130 /* 一度しか行わせたくない */ 131 socket.on( 132 'once', 133 () => 134 { 135 if(onceFlag) { 136 console.log('once'); 137 } 138 } ); 139 } ); 140 141// 公開フォルダの指定 142app.use( express.static( __dirname + '/public' ) ); 143 144// サーバーの起動 145server.listen( 146 PORT, 147 () => 148 { 149 console.log( 'Server on port %d', PORT ); 150 } );
クライアント側ではjqueryを用いてソースコードを用意して、onceのidを付けたdivタグを用意しておりました。
javascript
1$("#once").on( 2 'click', 3 () => 4 { 5 socket.emit('once'); 6 } 7);
上のイベントが発火したときに「once」のログが1度だけ残り、以後はクリックしてもログが残らないことは確認しております。
しかし、ほぼ同時に起こった場合はあくまで推測でしかなく、試せてない状況です。申し訳ございません。
すみません、よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー