Ext JSでのAMFデータの使用

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パケットが得られます。デコード後のデータにアクセスするには、パケットオブジェクトの以下のプロパティを使います。

レコードのグリッドへのロード

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()
});

AMF Grid

上記のコードでは、パケット内のどこに生のレコードデータがあるかに関して、いくつかの仮定を置いています。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グリッドの例を参照してください。

Last updated