note(旧)5万人に1人になる。この広告は、90日以上更新していないブログに表示しています。JavaScriptモチベーションなんかこうMMO的なゲームをブラウザで作りたいなあなんていう気持ちがありまして。そんなわけでWebGLのお勉強とかもしてるんですよ最近。同時にグラフィック的な部分以外の要素もしっかりやっていこうという思いがあるわけです。いうことで今アメーバピグのクローン的なものを作ってるわけです。その名もアオミドロピグ。名前を言うのは恥ずかしい。リポジトリはここです。AomidroPigg今チャットを実装しているのですが、実装に関して若干迷うなあーって部分があってそこがある程度自分の中でまとまってきたのでここに書いとこうということで今回の記事になります。環境package.jsonのdependenciesはこんな感じです。関係ないのも混ざってますけど察してください。"^3.7.0"}仕様viewはReactを使う送信したメッセージは全てDBに保存された上で他の端末に表示されるメッセージ入力中は「入力中...」の文字を表示させる悩んだところWebSocketの処理とDBの処理のフローどうするか問題NodeとWebSocketを使ってチャットを作るっていうのは以前にもやったことがあるのですが、そのチャットのメッセージの永続化を今回はやってみたかったのでメッセージをDBに入れる処理が必要になりました。なると、チャット入力欄をsubmitしたときに、DBに投げる処理とWebSocketとして投げる処理の2つの処理が必要になります。この2つの処理を並列で同時に走らせるべきなのか、それともWebSocketでサーバーに投げてサーバー側でDBに入れてコールバックでクライアントにWebSocketを返すべきなのか、みたいな選択肢で悩みました。DBの内容と表示されるチャットの内容が整合性保たれないとだめだから2つの処理は繋がりがないといけない気がするけれど、WebSocketはそのリアルタイム性が大事であることを考えるとDBに入れる処理を毎回挟むのはどうなのかなあとか悩んでました。これは結局以下の問題を解決するときに必然的にやり方が決まりました。Componentの中で、stateとして渡されたmessegeという配列の中身をmapで回して表示しています。このように回すと、jsxの中でkeyというattributeをつけないと怒られてしまいます。keyはuniqueでなければならないため、配列を回したときのindexをあてるのは間違っている、ということみたいです。React.jsの地味だけど重要なkeyについてそうなってくるとこれはもうkeyはDBに入れたときのメッセージのIDを使う必要があるということになります。その前提を元に考えるとDBに入れる処理とWebSocketの処理を別にしてしまうとメッセージのIDを取るのが難しくなってしまうため、必然的にWebSocketの処理とDBに入れる処理を直列で繋ぐ必要があることがわかりました。流れとしては、まずAさんがチャットのメッセージ入力欄からメッセージをsubmitします。メッセージはWebSocketを使ってサーバーに渡されます。サーバー側でその値をDBに入れて今入れたメッセージのIDを取得しつつコールバックでWebSocketを使ってそのメッセージをBさんに渡します。Componentの中で配列をmapで回して描画するわけですが、その際のkeyはメッセージのIDをあてます。これで、悩んでいた部分の1つは解決することができました。入力中を表示する処理はどうするか問題facebookのメッセンジャー等で見られる、チャットのメッセージ入力欄に文字を入れているときに相手には「入力中...」と表示される処理を実装したいってときに、上で述べたようなDB接続を挟む処理と一緒にやってしまうと、入力中情報はDBとかとは関係なく実装したいので上手くいかないなーってなってました。渡す処理と送信したメッセージを渡す処理は別の処理で実装することにしました。入力欄に入力したときにWebSocketで入力中であることを送信します。入力中情報に関してはサーバー側は何もせず、そのまま他のクライアントに渡します。受け取ったクライアントは「〇〇が入力中...」というメッセージを表示します。メッセージをsubmitしたとき、もしくは入力をやめたとき、入力をやめたことを送信します。受け取ったクライアントは「〇〇が入力中...」というメッセージを非表示にします。入力中の情報表示に関してはこんな感じ?ということで、入力中ということを表示させる処理と、実際にメッセージを送る処理は別で分けて作っています。入力中のイベントって一体どうやってハンドルするんだ「入力中である」なんていうイベントの取り方がいまいち良い方法が思いつかなかった。focus?いや、focusしてる間は入力中という判断にしてしまうとfocusだけされてる状態で放置してる状況のときも入力中扱いになってしまう...keydownされたときに発火させる?うーん、keydownイベントは複数起きまくるしなあ...そしてkeydownにした場合に、途中で入力をやめて送信せずに消した場合はどうやってイベントを取るのか...考えれば考えるほど想定しなければならないことが多いなあと実感する。結論として、入力欄にfocusしている状態でのkeydownイベントを取得してinputのvalueが存在していたら入力中という情報を送り、2回目以降のkeydownイベントではinputのvalueが空にならない限りは何もしないでスルーする。空になった場合は入力中を非表示にする情報を送り、もしくはsubmitされた場合も入力中を非表示にする情報を送る。あとはblurのときも入力中を非表示にさせる。こんな感じでカバーできるかな?とは思うけれど、いかがでしょうか。誰か何か意見あったら教えていただけるとありがたいです。まとめこんな感じで悩みに悩みつつただ今Node.jsとWebSocketでチャットを実装している。終わってはいないけれど。上にあげたリポジトリを見てもらえれば現在の進捗がわかるのでもし興味がある人がいたら見てみてね。こちらからは以上です。...これに行ってきたのでそのメモ。@サイボウズ株式会社これに行ってきたのでそのメモ。@...これに行ってきたのでそのメモ。WebGL技術系の話だったりゲームの話だったりポエムだったりを綴っていきます。読者になるRECENTLYブログをHugoに移しました。メモツールを作りたい。@株式会社オプト5万人に1人になる。(1)SEARCHはてなブログをはじめよう!nabeliwoさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。