質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

3248閲覧

WebsocketとRatchetのサンプルコードについて

退会済みユーザー

退会済みユーザー

総合スコア0

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2017/11/10 06:47

Websocket及び、JQueryについての知識が乏しい者ですので、お恥ずかしい質問かもしれませんがお答えいただければ助かります。

html

1<!DOCTYPE html> 2<html lang="ja"> 3<meta charset="utf-8"> 4<title>Chat</title> 5<style> 6.container { 7 width: 600px; 8} 9.box{ 10 overflow:hidden; 11} 12.left { 13 background-color: #D3D3D3; 14 padding: 20px; 15 margin: 5px; 16 width: 300px; 17 float:left; 18 border-radius:10px; 19} 20.right { 21 background-color: #ADFF2F; 22 padding: 20px; 23 margin: 5px; 24 width: 300px; 25 float:right; 26 border-radius:10px; 27} 28</style> 29<script src="http://code.jquery.com/jquery-2.2.4.js"></script> 30<script> 31(function($){ 32 var settings = {}; //変数settingsを空で置く 33 34 var methods = { //ここから変数methodに各methodを代入していく 35 init : function( options ) { 36 settings = $.extend({ 37 'uri' : 'ws://localhost:8080', //URIとは名前または場所を識別する書き方のルールの総称(親玉)。 38 //URLやURNは、URIで定められたルールに従って書かれたり使われたりする。 39 //'key':'値'の関係 40 //ここでは連想配列を作っているのと同じ。 41 'conn' : null, 42 'message' : '#message', 43 'display' : '#display' 44 }, options); 45 $(settings['message']).keypress( methods['checkEvent'] ); 46 //settingsにextendで代入されているmessageの値#messageにキーボード上に反応があった際に、method[checkEvent]を行う 47 //input type text id="message"へのキーボードのアクセスがあった際にcheckEventが発動。 48 $(this).chat('connect'); 49 }, 50 51 52 checkEvent : function ( event ) { //書き込み用のmethod。 53 if (event && event.which == 13) { //13? 54 var message = $(settings['message']).val(); 55 //input type=text id="message"のval()を代入 56 if (message && settings['conn']) { 57 settings['conn'].send(message + ''); 58 //websocketに変数messageを挿入 59 $(this).chat('drawText',message,'right'); 60 //drawTextでhtmlを精製、 61 $(settings['message']).val(''); 62 } 63 } 64 }, 65 66 connect : function () { 67 if (settings['conn'] == null) { 68 settings['conn'] = new WebSocket(settings['uri']); 69 settings['conn'].onopen = methods['onOpen']; 70 settings['conn'].onmessage = methods['onMessage']; 71 settings['conn'].onclose = methods['onClose']; 72 settings['conn'].onerror = methods['onError']; 73 } 74 }, 75 76 onOpen : function ( event ) { 77 $(this).chat('drawText','サーバに接続','left'); 78 }, 79 80 onMessage : function (event) { 81 if (event && event.data) { 82 $(this).chat('drawText',event.data,'left'); 83 } 84 }, 85 86 onError : function(event) { 87 $(this).chat('drawText','エラー発生!','left'); 88 }, 89 90 onClose : function(event) { 91 $(this).chat('drawText','サーバと切断','left'); 92 settings['conn'] = null; 93 setTimeout(methods['connect'], 1000); 94 }, 95 96 drawText : function (message, align='left') { 97 if ( align === 'left' ) { 98 var inner = $('<div class="left"></div>').text(message); 99 } else { 100 var inner = $('<div class="right"></div>').text(message); 101 } 102 var box = $('<div class="box"></div>').html(inner); 103 $('#chat').prepend(box); 104 }, 105 }; // end of methods 106 107 $.fn.chat = function( method ) { 108 if ( methods[method] ) { 109 return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); 110 } else if ( typeof method === 'object' || ! method ) { 111 return methods.init.apply( this, arguments ); 112 } else { 113 $.error( 'Method ' + method + ' does not exist' ); 114 } 115 } // end of function 116})( jQuery ); 117 118$(function() { 119 $(this).chat({ 120 'uri':'ws://localhost:8080', 121 'message' : '#message', 122 'display' : '#chat' 123 }); 124}); 125</script> 126</head> 127<body> 128 <input type="text" id="message" size="50" /> 129 <div id="chat" class="container"></div> 130</body> 131</html> 132

php

1<?php 2use Ratchet\Server\IoServer; 3use Ratchet\Http\HttpServer; 4use Ratchet\WebSocket\WsServer; 5use MyApp\Chat; 6 7 require dirname(__DIR__) . '/vendor/autoload.php'; 8 9 $server = IoServer::factory( 10 new HttpServer( 11 new WsServer( 12 new Chat() 13 ) 14 ), 15 8080 16 ); 17 18 $server->run(); 19

コメントアウトに関しては、一つ一つ整理するために記入しております。
間違い、勘違いなどありましたらご教授いただければ幸いです。
上記2つのファイルはRatchetのマニュアルをそのままコピーして貼り付けたものになります。
htmlファイルのscript内にある$.fn.chatというメソッドがあるのですが、処理の内容が全く理解できず、頭を抱えております。$.fn(JQueryプラグイン)がなぜ記入する必要があるのか?
またchatメソッドがどういう処理をこの場合行なっているのか?
かなり丸投げな質問であることは重々承知しております。
当然一つ一つバラして検索するなどし、理解しようと試みたのですが、やはりchatメソッドの動作が理解できませんでした。引き続き理解に努めるよう努力いたしますが、ヒントなどでも結構ですので皆様の御知恵をお貸しいただければ幸いです。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

$.fnはjQueryオブジェクト($(truthy)として返って来るもの)のプロトタイプです。
jQueryプラグインでなくても、サンプルコードなら使用して良いのではないでしょうか。

結論からいうと、この関数はあまり意味がありません。
意図を想像することはできるのですが、その機能を実現できていません。
以下説明です。

説明

この$.fn.chatには二つの機能があります。

第一の機能: 内部でのthisを保持したメソッド呼び出し

js

1if ( methods[method] ) { 2 return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); 3}

の部分がそれを行います。
使用している箇所は全て$(this).chat('...', ...)の形です。
この機能では、methods[1番目の引数(メソッド名)]という関数を自分のthisと自分に渡された2番め以降の引数(Array.prototype.slice.call( arguments, 1 ))で呼び出しています。

なぜこんなことをしているか、私はこのプログラムの著者でないのでわかりませんが、以下のような理由が考えられます。
Javascriptのthisは変わっていますが、このプログラムの構成では普通の動作が問題になります。
このプログラムは「アプリケーションのためにオブジェクトを作るほどではないがthisとして設定を取り回したい」という微妙な規模です。(少なくとも著者はそう思ったようです)
しかし、そうすると実行したい処理が取り回したいオブジェクトのメソッドでないという状況になります。
メソッドにせずにthisを保つにはFunction.prototype.apply(以下apply)を使いたくなります。そしてapplyを書きまくるとコードが散らかるのでその部分を関数にしたいと考えます。
ところが作った関数を普通に呼び出すとthisは変わってしまいます
thisを保つには、Function.prototype.applyを使うかメソッドにするかしかありません。堂々巡りです。
そこで、そのthisを保ちながらapplyする関数を持っておくクラスをjQueryに兼ねてもらうことにしたようです。

第二の機能: 外部からのオプション指定の受け付け

js

1else if ( typeof method === 'object' || ! method ) { 2 return methods.init.apply( this, arguments ); 3}

の部分がそれを行います。
applyを使って引数とthisを投げています。

ここでもthisを保つようにしているようです。
現状ではthisを保っても意味はありませんが、コードを拡張していくうちに、どこかのdivの中にチャット画面を出すという機能を持たせることになるかもしれません。
その時に、$(対象の要素).chatで呼び出され、thisとして対象の要素必要が出てきます。
それを見越してこういう作りになっているのでしょう。

おかしなところ

ある程度普通の話なので、この辺りまではわかっているかもしれません。
ところが、thisとしてjQueryオブジェクトを持って、それがチャット画面につながると考えると、このコードにはおかしなところがあります。
init, connect, drawTextは$.fn.chat越しで呼ばれていますが他はイベントハンドラとして呼び出されており、そのためにthisが変わってしまっています。
特に、onOpen,onMessage,onError,onCloseではWebsocketオブジェクトをjQueryに渡したオブジェクトが生成されており、このオブジェクトをjQueryオブジェクトとして使うと、関数によってはエラーが発生してしまいます。

おそらく途中で気が変わってthisを保つことをやめたのに、methods.なんとか()の形への書き換えをしなかったのでしょう。
つまり、この$.fn.chatには意味がありません。

実際、$.fn.chatを取り除いて以下のようにしても動作しました。

js

1<!DOCTYPE html> 2<html lang="ja"> 3<meta charset="utf-8"> 4<title>Chat</title> 5<style> 6.container { 7 width: 600px; 8} 9.box{ 10 overflow:hidden; 11} 12.left { 13 background-color: #D3D3D3; 14 padding: 20px; 15 margin: 5px; 16 width: 300px; 17 float:left; 18} 19.right { 20 background-color: #ADFF2F; 21 padding: 20px; 22 margin: 5px; 23 width: 300px; 24 float:right; 25 26} 27</style> 28<script src="http://code.jquery.com/jquery-2.2.4.js"></script> 29<script> 30(function($){ 31 var settings = {}; 32 33 var methods = { 34 init : function( options ) { 35 settings = $.extend({ 36 'uri' : 'ws://localhost:8080', 37 'conn' : null, 38 'message' : '#message', 39 'display' : '#display' 40 }, options); 41 $(settings['message']).keypress( methods['checkEvent'] ); 42 methods.connect(); 43 }, 44 45 checkEvent : function ( event ) { 46 if (event && event.which == 13) { 47 var message = $(settings['message']).val(); 48 if (message && settings['conn']) { 49 settings['conn'].send(message + ''); 50 methods.drawText(message,'right'); 51 $(settings['message']).val(''); 52 } 53 } 54 }, 55 56 connect : function () { 57 if (settings['conn'] == null) { 58 settings['conn'] = new WebSocket(settings['uri']); 59 settings['conn'].onopen = methods['onOpen']; 60 settings['conn'].onmessage = methods['onMessage']; 61 settings['conn'].onclose = methods['onClose']; 62 settings['conn'].onerror = methods['onError']; 63 } 64 }, 65 66 onOpen : function ( event ) { 67 methods.drawText('サーバに接続','left'); 68 }, 69 70 onMessage : function (event) { 71 if (event && event.data) { 72 methods.drawText(event.data,'left'); 73 } 74 }, 75 76 onError : function(event) { 77 methods.drawText('エラー発生!','left'); 78 }, 79 80 onClose : function(event) { 81 methods.drawText('サーバと切断','left'); 82 settings['conn'] = null; 83 setTimeout(methods['connect'], 1000); 84 }, 85 86 drawText : function (message, align='left') { 87 if ( align === 'left' ) { 88 var inner = $('<div class="left"></div>').text(message); 89 } else { 90 var inner = $('<div class="right"></div>').text(message); 91 } 92 var box = $('<div class="box"></div>').html(inner); 93 $('#chat').prepend(box); 94 }, 95 }; // end of methods 96 97 $(function() { 98 methods.init({ 99 'uri':'ws://localhost:8080', 100 'message' : '#message', 101 'display' : '#chat' 102 }); 103 }); 104})( jQuery ); 105 106</script> 107</head> 108<body> 109 <input type="text" id="message" size="50" /> 110 <div id="chat" class="container"></div> 111</body> 112</html> 113

その他

js

1var settings = {}; //変数settingsを空で置く

空**のObject**であることをはっきりと意識した方が良いかもしれません。
Javascriptには空の文字列、NaN、null、undefined、空のArrayなど色々な「空っぽいもの」があります。
……というか、ここに値を足していくんじゃないんですね。型宣言かなにかなんでしょうか。

js

1var methods = { //ここから変数methodに各methodを代入していく

正確には各メソッドの代入ではありません。これはオブジェクト初期化子です。
これを代入と呼ぶと以下のような問題があると思います。

  • setterなどの理解に影響をきたすかもしれない
  • 先に書いたものでも定義に使用できないということが理解しにくくなるかもしれない

js

1if (event && event.which == 13) { //13?

13はKeyboardEvent.whichの値としてEnterキーを表します。(参考

投稿2017/11/11 12:47

miimou

総合スコア74

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/14 08:00

遅くなり大変申し訳ありませんでした。 オブジェクト初期化子という言葉を初めて目にしました。他にも自分が理解できていなかった部分をここまで詳しく解説していただき感謝しております。 まだまだ自分の知識が足りないことを痛感しましたが、一つ一つ身につけていこうと思います。本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問