Action Message Format(AMF)は、Adobe Flash/FlexがActionScriptのオブジェクトグラフをシリアライズするために使う、コンパクトなバイナリフォーマットです。AMFは一般に、Adobe Flashクライアントとリモートサービスとの間で送信されるメッセージのエンコードに使われます。AMFは単なるシリアライゼーションの手法であって、トランスポートではありません。したがって、AMFでエンコードされたバイナリデータは、HTTPやHTTPSのような任意のトランスポートで利用できます。このガイドでは、ウェブブラウザ内からHTTP経由で送信されるAMFデータを、Ext JSとAJAXが、Flashプラグインを使わずに、どのようにして消費するかを説明します。このガイドでは、Ext JSのデータパッケージやグリッドコンポーネントに関して、ある程度経験のある読者を想定しています。
注意:_この機能はSencha Completeをお買い上げいただくことにより、ご利用いただけます。このクラスの使用に関する詳細は、当社のSencha Completeの製品ページをご覧ください。_
AMFパケットの処理
AMFでエンコードされたオブジェクトグラフは、通常「AMFパケット」というフォーマットで作成されます。AMFパケットの中には、複数のヘッダーやメッセージがバッチ化されています。ここでは、Ext JSを使ってAMFパケットをデコードして、ヘッダーやメッセージにアクセスする方法を見てみましょう。まず、バイナリAMFパケットデータを返すURLに、AJAXリクエストを行います。
Ext.Ajax.request({
url: 'some/url',
binary: true,
success: function(response) {
console.log(response.responseBytes);
}
});
コンソールにはバイト配列が表示されるはずです。この配列は、ブラウザがサポートしている場合にはUint8Array、していない場合には単なる数値のArrayになります。この配列は、AMFパケットを構成する生のバイトです。AJAXリクエスト上のExt.data.Connection#binaryコンフィグをtrueに設定することを忘れないでください。そうすることにより、レスポンスはバイナリデータとして解釈され、レスポンスオブジェクトにresponseBytes
プロパティが設定されるようになります。
ここで得られたのは生のバイナリデータなので、役に立つ情報を得るには、このデータをデコードする必要があります。そのためには、Ext.data.amf.Packetクラスを使います。successコールバック関数の中に以下のコードを追加して、新しいPacketを生成します。
var packet = Ext.create('Ext.data.amf.Packet');
これにより、作業用の空のAMFパケットオブジェクトが生成されます。Packetクラスには、AMFフォーマットのバイナリデータをデコードするために必要なロジックが含まれています。AMFバイト配列をデコードするには、単に配列をPacketのExt.data.amf.Packet#decodeメソッドに渡します。
packet.decode(response.responseBytes);
これで、完全にデコードされたAMFパケットが得られます。デコード後のデータにアクセスするには、パケットオブジェクトの以下のプロパティを使います。
- Ext.data.amf.Packet#version - パケットのAMFバージョン
- Ext.data.amf.Packet#headers - パケットのヘッダー
- Ext.data.amf.Packet#messages - パケットのメッセージ
レコードのグリッドへのロード
AMFパケットの使い方はわかったので、AMFでエンコードされたレコードを、Ext.data.amf.ProxyおよびExt.data.amf.Readerを使って、Ext JS Ext.data.Storeにロードし、Ext.grid.Panelに表示する方法を学びましょう。この例では、さまざまな言語のパングラムのリストを含むAMFパケットから、レコードをロードします。まず、Ext.data.Modelを定義します。
Ext.define('Pangram', {
extend: 'Ext.data.Model',
fields: [
{ name: 'language', type: 'string' },
{ name: 'text', type: 'string' }
]
});
次に、このモデルインスタンスを含むExt.data.Storeを作成します。このストアを、Ext.data.amf.Proxyを使って設定します。AMFプロキシは、デフォルトではExt.data.amf.Reader を使います。したがって、リーダーのデフォルト設定を変更する必要がなければ、リーダーを明示的に設定する必要はありません。
var store = Ext.create('Ext.data.Store', {
model: 'Pangram',
proxy: {
type: 'amf',
url: 'some/url',
},
autoLoad: true
});
最後に、先ほど作成したストアに結びついたExt.grid.Panelを作成します。
Ext.create('Ext.grid.Panel', {
title: 'AMF0 Pangrams',
height: 350,
width: 700,
store: store,
columns: [
{ text: 'Language', dataIndex: 'language', width: 130 },
{ text: 'Pangram', dataIndex: 'text', flex: 1 }
],
renderTo: Ext.getBody()
});
上記のコードでは、パケット内のどこに生のレコードデータがあるかに関して、いくつかの仮定を置いています。Ext.data.amf.Readerは、デフォルトでは、パケットの最初のメッセージ本体が、レコードデータを含むオブジェクトの配列であると想定します。けれども、これが常に正しいとは限りらないので、メッセージ本体のどこからレコードを探すかを、リーダーに教えなければならないことがあります。そのためには、リーダーのExt.data.Reader#root設定プロパティを使います。
proxy: {
type: 'amf',
url: 'some/url',
reader: {
type: 'amf',
root: 'foo.bar'
}
}
このプロパティは、メッセージ本体が「foo」という名前のプロパティを含むオブジェクトであり、そのプロパティは「bar」という名前のプロパティを含むオブジェクトであり、この「bar」の値が生のレコードデータオブジェクトの配列であることを伝えます。
AMF Packetには、複数のメッセージが含まれている可能性があります。Ext.data.amf.Reader#messageIndexコンフィグを使うと、リーダーがレコードを探すメッセージを設定することができます。
reader: {
type: 'amf',
messageIndex: 42
}
実例やソースコードについては、AMFグリッドの例を参照してください。