FlexにはArrayCollectionというArrayとほとんどおなじようなものがある。
しかし、ArrayCollectionには変更時のイベントがあるので、これを使ってちょっと便利なことができる。
(というより、私にとっては困った非同期処理への苦肉の策とでもいうのでしょうか?)
私がこの機能を使おうと思ったのは、pop3クライアントを作っているのだが
(出来上がったら公開しようと思っていますが、まだ、ちょっと文字化け関連でバグがありまして・・)
Socket通信は非同期処理になってしまうということでした。
つまり、2通のメールを取得しようとしても、受信しているデータがどちらのメールかの保障がないということになります。
2つのオブジェクトを作ってしまえば2通の場合にはそれでもいいのですが、1000通の場合なら、1000個のオブジェクト?
ということになるとちょっと抵抗があったので、1通目の取得が終わったら2通目を取りにいくということを実装しようと思い、
ここで、非同期処理を同期化(というのでしょうか?)させなくてはなりません。
探していると、そんなようなライブラリがあったのですが、ArrayCollectionの変更のイベント処理を使えば簡単にできそうだったので、
それで実装してしまいました。
要は簡単です。
pop3.readMail(1);
pop3.readMail(2);
のような感じメールを読むメソッドを実行したときにこの命令をArrayCollectionにためておきます。
private function readMail(i:int):void{
var cmd:Object = new Object();
cmd.key = "RETR";
cmd.value = i;
arraycollection.addItem(cmd);
}
のような感じで・・・・
それで、arrayCollectionには、
arraycollection.addEventListener(CollectionEvent.COLLECTION_CHANGE,executeCmd);
のように、変更された時にexecuteCmdメソッドという感じで実行するようにしておくのです。
ただし、これを単純にやってしまっては非同期処理が連続で動いてしまうだけです。
そこで、
private function executeCmd(ce:CollectionEvent):void{
if(arraycollection.length> 0 ){
arraycollection.removeEventListener(CollectionEvent.COLLECTION_CHANGE, executeCmd);
var cmd:Object = arraycollection.removeItemAt(0);
// 何らかの受け取ったcmdの処理をする
executePopCmd(cmd);
}
}
このようにしておけば、2回目のreadMailメソッドでもメールを読みに行かないということです。
しかし、さらにこのままでは、永久に2回目のreadMailが実行されないことになってしまいます。
(上の例では、executePopCmd でPOP3のプロトコルを処理するものとしてみてください)
Socketですので実際には、ソケットからデータを読むということが非同期処理として扱わなければいけないのですが、
POP3の特徴としてデータの最後には.(ドット)で終了するという特徴があるので、
その終了処理の部分でarrayCollectionからreadMail(2)で蓄積されたタスクを取りだし、また、実行するというわけです。
そして、これをぐるぐると繰り返し、arrayCollectionが空っぽになったら、
arraycollection.addEventListener(CollectionEvent.COLLECTION_CHANGE,executeCmd);
のようにまた、変更時のイベントを登録しておけば、順次処理をしていかなければいけないが、非同期処理が邪魔してしまうものに対しても有効です。
もっと、もっと汎用的につくられたライブラリを探してきてもいいのでしょうが、実際にはある程度用途が定まってしまえば、
このような方法で回避するのもいいのかなと思っています。

