Movatterモバイル変換


[0]ホーム

URL:


ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

この広告は、90日以上更新していないブログに表示しています。

IE 10 の拡張された XHR を使って HTTP のストリーミングを受信する (Twitter Streaming API とか)

Web ブラウザから web サーバーに HTTP リクエストを送る際によく用いられるXMLHttpRequest (XHR) ですが、XMLHttpRequestAPI を見ると、chunked transfer encoding による HTTP のストリーミングからのデータを受信して、都度処理をしていく、というような使い方ができるようにはなっていないと思います。

Internet Explorer 10 (IE 10) では、そういうことができるように拡張された XMLHttpRequest が実装されています ので紹介します。

少ないデータ量なら COMET Streaming で対応できるが...

もちろん、通常のXMLHttpRequest でも chunked transfer encoding なデータを受け取ることはできますし、データの受信が進むたびに progress イベントが発生しますので、受け取るデータが少量の場合はなんとかなります。 詳しくは以下のページをご覧ください。

しかしながら、受け取ったデータはXMLHttpRequest の接続が終了するまでXMLHttpRequest オブジェクトの中にため続けられますので、長時間 HTTP 接続を保ったまま、送られてきたデータを都度処理していく というようなことができません。 データがどんどんたまっていきますので、やがてメモリ不足になってしまいます。

具体的には、Twitter が Streaming API を chunked transfer encoding で送ってきます ので、XMLHttpRequestTwitter StreamingAPI を扱いたい場合に困りますね。

IE 10 の拡張された XHR なら HTTP のストリーミングも扱える

まあ普通のブラウザ上でTwitter の StreamingAPI なんて使えなくてもいいでしょ、って感じもしますが、最近はブラウザの拡張機能やら Windows ストアアプリ (旧称 Metro アプリ) やらでJavaScript からTwitter StreamingAPI を使いたくなることがしばしばあります。 というわけで、Windows ストアアプリをJavaScript で書くときに使える IE 10 の拡張されたXMLHttpRequest を使って、chunked transfer encoding で送られてきたデータを都度処理していく方法について書いておきます。

HTTP ストリーミングを扱う方法

HTTP ストリーミングを扱うためには、リクエストを送る前に、XMLHttpRequest#responseType プロパティに "ms-stream" を設定します。

ダウンロード要求の responseType プロパティが "ms-stream" に設定されている場合、次の例に示すように、実行中にコンテンツを操作できます。

http://msdn.microsoft.com/ja-jp/library/ie/hh673569%28v=vs.85%29.aspx
レスポンスの受け取り

次に、レスポンスの受け取り方について説明します。 readyStateChange イベントでXMLHttpRequest#readyState プロパティがXMLHttpRequest.LOADING になったときにストリーミングを受け取れるようになっていますので、その中でストリーミングの処理を開始します。 ストリーミングで受け取ったデータは、XMLHttpRequest#response プロパティの値に入っている MSStream オブジェクトで表されます。

MSStream オブジェクトからデータを取り出す方法

MSStream オブジェクトは、Windows.Storage.Streams.IInputStream インターフェイスを実装したオブジェクト (IInputStream オブジェクト) をラップしたもので、実際のストリームは IInputSteram オブジェクトで表されます。

MSStream オブジェクトからデータを読み出す方法としてはMSStreamReader を使う方法もありますが、どうやら MSStreamReader ではデータを受信する都度データを読み出す、というようなことができない (すべてのデータを読み込んでから最後に読み出すしかできない) ようだったので、MSStream オブジェクトではなく、その下にある IInputStream オブジェクトを直接操作してデータを読み出すしかなさそうです。

MSStream のドキュメントにはMSStream#msInputStream プロパティ というものが存在しますが、手元 (Windows 8RTM 版) で試したところそのようなプロパティは存在せず、代わりに MSStream#msDetachStream メソッドというのが存在しました。 このメソッドを使うと、MSStream オブジェクトとその下にある IInputStream オブジェクトが切り離され、切り離された IInputStream オブジェクトを返り値として得ることができます。IInputStream オブジェクトの readAsync メソッド を使うことで*1、データを受け取るたびにデータの読み出しを行って処理を進めることができます。

サンプルコード

Windows ストアアプリ開発時に使えるサンプルコードとして、WinJS.xhr (XMLHttpRequest を扱う便利関数) で HTTP ストリーミングを扱う例を示します。

varuri ="http://www.example.com/test_stream";WinJS.xhr({ url:uri, responseType:"ms-stream"}).then(function (req){// 完了したときの処理// ...},function onError(err){// エラーが発生した時の処理// ...},function onProg(req){// streaming の読み込みを開始した時に以下の if 文の中に入るif (req.readyState === req.LOADING){// res は MSStream オブジェクトvar res = req.response;// msDetachStream メソッドを呼び出すことで IInputStream オブジェクトを res から切り離して取り出すvar stream = res.msDetachStream();// さらに stream からデータを読み込む処理に移る// ...}}).done(null,function (err){// 例外発生時の処理// ...});

余談 : その他のストリーミング関係の話

JavaScriptTCP/IP 上のストリーミングを扱うならば、HTTP の chunked transfer encoding を使うよりも以下の 2 つのどちらかを使う方が便利な気がします。Twitter StreamingAPI のようにサーバー側がすでに存在している場合はどうしようもないですが、新たに (サーバー側も含めて )Twitter StreamingAPI みたいなものを実装するのであれば、Server-Sent Events を使うのが良さそうです。

  • Server-Sent Events : HTTP 上で動作; サーバーからの push 配信を受け取る
  • WebSocket : TCP 上で動作; クライアントとサーバーの双方向通信

*1:もしくは IInputStream からデータを読み出すためのオブジェクトを操作することで

注目記事
検索
最近のコメント
    カテゴリー

    引用をストックしました

    引用するにはまずログインしてください

    引用をストックできませんでした。再度お試しください

    限定公開記事のため引用できません。

    読者です読者をやめる読者になる読者になる

    [8]ページ先頭

    ©2009-2025 Movatter.jp