将Web服务结果与Flex中的请求进行匹配

时间:2009-01-22 10:53:45

标签: flex web-services actionscript asynchronous

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

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

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

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而不是mx.rpc.events.ResultEvent继承ResultEvents。我不完全确定它为什么这样做 - 访问AsyncToken的唯一方法是它最初由方法调用返回。

3 个答案:

答案 0 :(得分: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文章here

答案 1 :(得分: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}" />

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

答案 2 :(得分:1)

我担心我并不完全理解你要做的所有事情,但是如果我理解正确,你会发出许多请求并异步获得多个回复,并且你试图将响应与请求。

我过去已经针对类似的问题做了这个,我在文本字段中调用了关键字的web服务来执行“当你键入时搜索”这类功能,但这意味着我总是只关心最后一个请求的响应。所以我更改了服务以获取时间戳的参数(下降到毫秒)并将其与其余响应一起返回。然后我可以在响应中或在flex侧查找最新的时间戳,跟踪上一个请求的时间戳并查找该特定响应。

您也可以使用任何类型的UUID或任何唯一的UUID。它在服务方面需要更多的工作,但它可以很好地扩展并且易于理解。

你可以看到的另一件事,我为不自己研究这个问题道歉,就是在请求和生成的响应对象中查看调试。您可能会找到一些辅助信息,您可以查看这些对象以进行匹配。但我担心这在很大程度上取决于你如何打电话和接收回应。

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