3

在我回答这个问题之前,有一点(!)一点背景知识:

我有一个装有网格数组的手风琴控件,每个网格都是延迟加载的东西数组。我正在使用自动生成的 Web 服务代理来检索这些列表。我希望用户能够更改手风琴中选定的子项,而无需等待 Web 服务响应。我最初对所有请求使用相同的代理实例,并按照发出的顺序跟踪请求,但这样做的问题是较短的数组从服务器返回的速度更快,因此发出请求的顺序变得无关紧要.

在处理代理结果事件时,我找不到一个明显的方法来确定原始请求,所以我最终得到的是一个函数,它处理手风琴上的更改事件,实例化一个新的 web 服务代理,将其推入哈希表中选定子项的索引,然后添加一个闭包作为事件处理程序。即有点像这样:

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

(我试着匿名了一点,所以我可能错过了一些东西,但希望你明白)

那么,对于问题:有没有一种更简单的方法可以将代理结果与我刚刚丢失的原始请求相匹配?

如果不是,我所做的是否合理?我有点担心我最终可能生成然后正确处理它们的代理实例的数量(当有必要时) - 有没有我可能不知道的陷阱?

更新: 我认为可能会出现问题,因为生成的代理代码从 flash.events.Event 子类化 ResultEvents,而不是 mx.rpc.events.ResultEvent。我不完全确定它为什么这样做 - 访问 AsyncToken 的唯一方法是它最初由方法调用返回。

4

3 回答 3

8

不确定这是否有帮助,但我有类似的情况,我有一个 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 文章描述它:

于 2009-01-22T15:26:00.170 回答
1

好的,我想我明白了:由于请求是在选择时发出的,并且您通过本地代理进行调用,并且响应随机返回,因此您无法分辨哪个响应映射到哪个 UI 元素。说得通。

唔。如果不知道您的代理对象是什么“事物”,这很难说,但假设它是适当映射到 UI 对象的具体事物——例如,ListOfWidgets 到 DataGrid——那么最好让每个网格映射无论如何,它自己的 ListOfWidgets 代理实例。在这种情况下,当您实例化代理时,您可以将其结果应填充的网格的索引传递给它(类似于您在上面所做的,但目的是将索引存储为代理对象上的公共成员,而不是在一个单独的对象中)。然后,由于每个代理的结果事件处理程序应该通过事件的目标属性为您提供对代理的访问,您可以检索代理的目标索引(例如,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);
}

如果您使用数据绑定,编码模型会稍微简单一些,在这种情况下,您可以做更多类似的事情,前提是您的代理类或其结果集合被标记为可绑定:

<mx:DataGrid dataProvider="{proxy.results}" />

...并让事情“正常工作”(因为每个代理的实例都是唯一的)。这有意义吗?希望我已经正确理解了这个问题。;)

于 2009-01-22T14:19:42.923 回答
1

恐怕我不完全理解您正在尝试做的所有事情,但如果我理解正确,您正在发出许多请求并异步返回多个响应,并且您正在尝试将响应与请求相匹配。

我过去曾为类似的问题这样做过,我在文本字段中调用 keyup 上的 web 服务来执行“键入时搜索”之类的功能,但这意味着我总是只关心响应最后一个请求。因此,我将服务更改为还采用时间戳参数(精确到毫秒)并将其与其余响应一起返回。然后我可以在响应中或在 flex 端查找最新的时间戳,跟踪最后一个请求的时间戳并查找该特定响应。

您也可以使用任何类型的 UUID 或任何独特的东西来执行此操作。在服务方面需要做更多的工作,但它可以很好地扩展并且易于理解。

您可能会看到的另一件事,我很抱歉自己没有对此进行更多研究,即在调试中查看生成的请求和响应对象。您可能会在可以查看以进行匹配的那些对象中找到一些辅助信息。但我担心这将在很大程度上取决于你如何打电话和收到回复。

HTH 并希望我已经很好地理解了这个问题。

于 2009-01-22T14:31:20.153 回答