Немного (!) Предыстории, прежде чем я смогу перейти к вопросу:
У меня есть элемент управления «аккордеон», в который загружен массив сеток, каждая из которых лениво загружена массивами вещей. Я использую автоматически сгенерированный прокси-сервер веб-службы для получения этих списков. Я бы хотел, чтобы пользователь мог изменить выбранного дочернего элемента в аккордеоне, не дожидаясь ответа веб-службы. Изначально я использовал один и тот же экземпляр прокси-сервера для всех запросов и отслеживал запросы в том порядке, в котором они были сделаны, но проблема в том, что более короткие массивы возвращаются с сервера быстрее, поэтому порядок, в котором были сделаны запросы, становится неактуальным. .
Я не смог найти очевидный способ определить исходный запрос при обработке события результата прокси, поэтому в итоге я получил функцию, которая обрабатывает событие изменения на аккордеоне, создает экземпляр нового прокси-сервера веб-службы, помещает его в хеш-таблицу с индекс выбранного дочернего элемента, а затем добавляет закрытие в качестве обработчика события. то есть что-то вроде этого:
private proxyTable:Object = new Object();
private function PopulateThingGrid(index:Number):void
{
var grid:ThingGrid = myAccordion.getChildAt(index) as ThingGrid;
grid.things = ArrayCollection(proxyTable[index].getThings_lastResult);
}
private function SendThingRequest(index:int):void
{
var grid:ThingGrid= myAccordion.getChildAt(index) as ThingGrid;
if (grid.things.length == 0)
{
if (proxyTable[index] == null)
{
proxyTable[index] = new MyWebServiceProxy();
}
var proxy:MyWebServiceProxy= proxyTable[index];
proxy.addgetThingsEventListener(function ():void { PopulateThingGrid(index); });
var list:ThingList = thingLists.getItemAt(index) as ThingList;
proxy.getThings("thinglist", list.ListID);
}
}
private function myAccordion_Change(event:IndexChangedEvent):void
{
SendThingRequest(event.newIndex);
}(Я пытался немного анонимизировать это, так что, возможно, я что-то пропустил, но, надеюсь, вы уловили идею)
Итак, на вопрос (ы): есть ли более простой способ сопоставить результаты прокси-сервера с исходными запросами, которые мне просто не хватает?
Если нет, то разумно ли то, что я сделал? Меня немного беспокоит количество экземпляров прокси, которые я мог бы в конечном итоге сгенерировать, а затем правильно избавиться от них (когда это станет необходимым) - есть ли какие-то подводные камни, о которых я мог бы не знать?
Обновлять : Я думаю, что проблема может возникнуть из-за того, что сгенерированный прокси-код является подклассом ResultEvents из flash.events.Event, а не mx.rpc.events.ResultEvent. Я не совсем уверен, почему он это делает - единственный способ получить доступ к AsyncToken - это когда он изначально возвращается вызовом метода.





Хорошо, я думаю, что понимаю: поскольку запросы выполняются во время выбора, и вы звоните через локальный прокси, а ответы возвращаются случайным образом, вы не можете сказать, какой ответ соответствует какому элементу пользовательского интерфейса. Имеет смысл.
Хм. Трудно сказать, не зная, что это за «вещь» у вашего прокси-объекта, но если предположить, что это что-то конкретное, которое соответствующим образом отображается на объект пользовательского интерфейса - скажем, ListOfWidgets в DataGrid - тогда, вероятно, лучше иметь каждую карту сетки в любом случае в собственный экземпляр прокси ListOfWidgets. В этом случае, когда вы создаете экземпляр прокси, вы можете передать ему индекс сетки, которую должны заполнить его результаты (аналогично тому, что вы делаете выше, но с намерением сохранить индекс как публичный член на прокси-объекте, в отличие от отдельного объекта). Затем, поскольку каждый обработчик события результата прокси-сервера должен предоставлять вам доступ к прокси-серверу через свойство target события, вы можете получить целевой индекс прокси (например, event.target.index) и заполнить соответствующую сетку.
public class MyProxy
{
public var targetIndex:uint;
public function MyProxy()
{
// ...
}
}
private function handleSelection():void
{
var proxy:MyProxy = new MyProxy();
proxy.addGetThingsEventListener(Event.YOUR_RESULT_EVENT, yourHandler);
proxy.targetIndex = 1;
}
private function yourHandler(event:Event):void
{
fillGridWithResults(event.target.targetIndex);
}
Модель кодирования немного проще, если вы использовали привязку данных, и в этом случае вы могли бы сделать что-то подобное, если ваш прокси-класс или его коллекция результатов были помечены как Bindable:
<mx:DataGrid dataProvider = "{proxy.results}" />
... и все должно "просто работать" (поскольку каждый экземпляр прокси будет уникальным). Имеет ли это смысл? Надеюсь, я правильно понял проблему. ;)
Боюсь, я не полностью понимаю все, что вы пытаетесь сделать, но, если я правильно понимаю, вы делаете много запросов и получаете несколько ответов асинхронно, и вы пытаетесь сопоставить ответ с запросом.
Я делал это в прошлом для аналогичной проблемы, я вызывал веб-сервис при нажатии клавиш в текстовом поле, чтобы выполнить функцию типа «поиск по мере ввода», но это означало, что меня всегда заботил только ответ для последний запрос. Поэтому я изменил службу, чтобы она также принимала параметр отметки времени (с точностью до миллисекунды) и возвращала ее обратно с остальной частью ответа. Затем я мог либо искать последнюю временную метку в ответах, либо на стороне гибкости, отслеживать временную метку последнего запроса и искать этот конкретный ответ.
Вы также можете сделать это с любым типом UUID или чем-то уникальным. Со стороны обслуживания требуется немного больше работы, но он хорошо масштабируется и легко понимается.
Еще одна вещь, на которую вы, возможно, могли бы взглянуть, и я прошу прощения за то, что не исследовал это самостоятельно, - это посмотреть в отладке на сгенерированные объекты запроса и ответа. Вы можете найти некоторую вспомогательную информацию с этими объектами, на которые вы можете посмотреть, чтобы выполнить сопоставление. Но я боюсь, что это будет во многом зависеть от того, как именно вы звоните и получаете ответ.
HTH и надеюсь, что я достаточно хорошо понял проблему.
Я рассматривал что-то подобное, но я бы предпочел не менять сам веб-сервис (это проект .NET, который я хочу пока оставить в покое - от него зависят другие вещи).
Не уверен, что это помогает, но у меня была аналогичная ситуация, когда у меня был RemoteObject, для которого я вызываю 4 метода CRUD, но только один resultHandler. Я решил это с помощью AsyncToken.
Мои вызовы RemoteObject выглядели так:
public function list() {
var token:AsyncToken = myService.list();
token.operation = "list";
}
public function update() {
var token:AsyncToken = myService.update(selectedItem);
token.operation = "update";
}
public function create() {
var token:AsyncToken = myService.create(selectedItem);
token.operation = "create";
}
public function delete() {
var token:AsyncToken = myService.delete(selectedItem);
token.operation = "delete";
}
Тогда resultHandler выглядит так:
public function resultHandler(event:ResultEvent):void {
if ( event.token.operation == "list" ) {
// do something
} else if ( event.token.operation == "update" ) {
// do something
}
// etc...
operation - это динамическое свойство, а не член AsyncToken, поэтому вы можете называть его как хотите.
Есть статья в Cookbook с описанием этого здесь:
Это превосходно и должно делать именно то, о чем просит плакат. Хотел бы я добавить этот ответ в избранное. Это именно то, о чем я думал в последнем абзаце своего ответа.
Я посмотрел на AsyncTokens, возвращаемые методом getThings, но это действительно полезно, только если я сам напишу прокси-класс веб-службы - GetThingsResultEvent не имеет свойства токена.
На самом деле, поразите это, я думаю, что могу добавить свои обработчики событий к самому токену, а не привязываться к (поддельным / неправильным) событиям, которые имеет веб-сервис. В следующий раз я могу написать код веб-сервиса вручную!
Да, AsyncToken должен помочь вам. Но вы правы - использование прокси WebService может быстро стать проблемой. Я много раз возился с ними, пытаясь заставить их работать так хорошо, как кажется, что они должны (с .NET и WCF), но в конечном итоге свернул и свой собственный.
В этом есть смысл, да, но я не думаю, что это решение, которое я могу легко использовать без изменения архитектуры прокси-класса (который в любом случае создается автоматически). Кроме того, прокси используется множеством других элементов управления и имеет множество других методов. то есть он не просто получает вещи, он также получает Foos, Bars, Bears, Rhinos ....