LoginSignup
3
3

More than 5 years have passed since last update.

MEAN環境でCOMET(Long polling)通信を作ってみた(個人メモ)

Last updated at Posted at 2014-07-07

目的

フロントAngularJS、バックNodejsのいわゆるMEAN環境でtwitterのstreaming APIを使ってCOMET通信をやってみた。今回は主に通信〜NodeJS側のセッション内での情報共有の部分でいくつかわかったことがあるのでメモとし残します。
・初歩的な情報も残す。
・Passportでの認証部分は結果的に何もノウハウがないので割愛。
・あくまでも個人メモなので、単体で動くコードは将来の努力目標とする。

ハマったところ

・フロント側とバック側が非同期で処理するのはJavascriptなので自然にそうなってしまうが、複数のHttpリクエスト間で情報共有する部分は意外と情報が少なく、トライ&エラーを繰り返した。
・ロングポーリングなので、ブラウザがリクエストを送って、結果が返ってくるまではずっと待ち続けるかというと、そうでもなかった。(少なくともChromeでは)リクエスト発行後120秒で接続が一旦切られてしまうので、そのあたりの考慮も必要。

通信部分の実装

・Angularからの初回$http.getでは(twitterの)Streamを呼び出すまでを処理し、StreamのCallback関数内で取得した(twitter)データをSessionStoreに追加する。この部分のポイントはsessionStoreの参照&格納する部分。

//sessionStore参照
req.sessionStore.get(req.sessionID, function (err, session){
}
//sessionStore格納 (req.session.save()でも良い)
req.sessionStore.set(req.sessionID, session, function (err){
}

・Angularからの2回め以降の呼び出しが実際にはLongPollingとなるが、普通通りに$http.get等で呼び出せば良い。NodeJsでは、上記と別の関数を準備して、上記関数でセッションに書きだした情報を読み書きしてやれば良い。setIntervalを使って数秒間隔でsession情報を問い合わせる。データがなければ繰り返し、あればフロントに戻す。ポイントだけ抜き出す。

//ブラウザが定期的にリクエストし直すために必要
if(req.listeners("close").length===0) {
  req.on("close", function() {
    // request closed unexpectedly
    clearInterval(interval);//タイマをストップ
  });
}
//sessionStoreからsession取得
req.sessionStore.get(req.sessionID, function (err, session){
}
//session格納
//req.sessionに格納しておけばreturn時にSessionStoreにコピーされる
req.session.statuses=session.statuses.splice(0);//sample
clearInterval(interval);//結果を返すためにタイマをストップ

感想

・DataStoreの動きが、responseありとなしでは全く違うので苦労した。
 →(データ取得側のような)responseなしの場合にはSessionStoreに直接格納する、またはrequest.session.save()のいずれか。
 →(データ返却側のような)responseありの場合には一旦request.sessionに格納してやる必要がある。SessionStoreに直接書いても上書かれるのでNG.

#やっぱり文字で書くとダメですね。シーケンス図をチャチャッと作れたらなあ。

後日談

twitterのStreaming APIを使って、タイムラインのユルユル表示をするということ自体は間違いではないだろうが、ほころびが目立ってきた。
・Strreaming APIをサーバ側で使用するということは、どうしてもセッション管理が複雑になってしまう。つまり、セッションごとにstatusesの取得結果を保持することになり、気まぐれなWEBクライアントの動き(ログアウトしない。いきなり切れる。)に合わせるとStreaming呼出し遮断とセッション情報のお掃除が必要となる。一ユーザが複数のセッションを張ることなどを考えると、セッションID毎でなく、ユーザ単位でやるべきか?等の考慮すべきことがまだあると思われる。つまるところ、複雑な仕組みになりすぎる。
・Streaming APIのstatuses/userにはなぜかパラメータでinclude_entitiesの指定ができない。このパラメータはtext部分の短縮形のURLを通常のURLに展開してくれるもので、Statusを画面表示する際には展開された形でなければわかりづらいと言える。また、URL展開のためのAPIも提供されていない。Streaming APIにこのオプションがないのは単純に「現在開発中」ということなのかもしれないが、REST APIのstatuses/home_timelineであれば使えるし、結局のところCOMETなども全部おしゃかにしてして作り直すべきなのかもしれない。(ほぼ結論が出ている。あとは開発時間の問題。)

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3