Flex的HTTPService调度ResultEvent而不是FaultEvent

时间:2014-05-26 18:32:09

标签: android actionscript-3 flex air flex-mobile

我想知道Flex的HTTPService何时启动ResultEvent以及何时调度FaultEvent。

当服务器响应包含401 http状态代码错误(未授权)时,HTTPService将调度ResultEvent而不是FaultEvent。我认为应该派遣一个FaultEvent。我对么?如果没有,请告诉我。

令人惊奇的是,当我在Flash Builder 4.7的Android模拟器下运行应用程序时,它会调度FaultEvent,但是当我在设备上运行它时,它会调度ResultEvent。为什么会这样?有什么想法吗?

测试应用程序代码

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">

   <fx:Script>
    <![CDATA[
        import mx.rpc.events.FaultEvent;
        import mx.rpc.events.ResultEvent;

        ///////////////////////////// USING HIGH LEVEL COMPONENT (FLEX) //////////////////////////////////////////

        /**
         * Checks if all the necesary data was entered by the user.
         */
        protected function configHandler(event:MouseEvent):void
        {
            textArea.text = "Connecting to server using a high level component";
            configurationService.url = "http://10.0.0.221/api/v1/room/current/";
            configurationService.headers.Accept = "application/json";  
            configurationService.send();
            textArea.appendText("\n...");
        }

        /**
         * Handles the first phase (getting basic application information) of the configuration. 
         * Stores the retrieved data from the server and calls the second phase of the process.
         */
        protected function serviceResultHandler(event:ResultEvent):void
        {
            textArea.appendText("\n");
            textArea.appendText("Entering serviceResultHandler \n");
            textArea.appendText(" HTTP status code is: " + event.statusCode);
        }

        /**
         * Handles errors within the first phase (getting basic application information) of the configuration process.
         */
        protected function servicefaultHandler(event:FaultEvent):void
        {
            textArea.appendText("\n");
            textArea.appendText("Entering servicefaultHandler \n");
            textArea.appendText("HTTP status code is: " + event.statusCode);
        }

        ///////////////////////////// USING LOW LEVEL COMPONENT (FLASH) //////////////////////////////////////////

        /**
         * Checks if all the necesary data was entered by the user.
         */
        protected function config2Handler(event:MouseEvent):void
        {
            textArea.text = "Connecting to server using a low level component \n ...";

            var loader:URLLoader = new URLLoader();
            var request:URLRequest = new URLRequest("http://10.0.0.221/api/v1/room/current/");
            request.requestHeaders = new Array( new URLRequestHeader('Accept','application/json'));

            try {
                loader.load(request);
            } catch (error:Error) {
                trace("Unable to load requested document.");
            }

            loader.addEventListener(Event.COMPLETE, completeHandler);
            loader.addEventListener(Event.OPEN, openHandler);
            loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
            loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

        private function completeHandler(event:Event):void {
            var loader:URLLoader = URLLoader(event.target);
            textArea.appendText("\n");
            textArea.appendText("Entering completeHandler \n");
            textArea.appendText("completeHandler: " + loader.data + "\n");

            var vars:URLVariables = new URLVariables(loader.data);
            textArea.appendText("The answer is " + vars.answer);
        }

        private function openHandler(event:Event):void {
            textArea.appendText("\n");
            textArea.appendText("Entering openHandler \n");
            textArea.appendText("openHandler: " + event);
        }

        private function progressHandler(event:ProgressEvent):void {
            textArea.appendText("\n");
            textArea.appendText("Entering progressHandler \n");
            textArea.appendText("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
        }

        private function securityErrorHandler(event:SecurityErrorEvent):void {
            textArea.appendText("\n");
            textArea.appendText("Entering securityErrorHandler \n");
            textArea.appendText("securityErrorHandler: " + event);
        }

        private function httpStatusHandler(event:HTTPStatusEvent):void {
            textArea.appendText("\n");
            textArea.appendText("Entering httpStatusHandler \n");
            textArea.appendText("httpStatusHandler: " + event);
        }

        private function ioErrorHandler(event:IOErrorEvent):void {
            textArea.appendText("\n");
            textArea.appendText("Entering ioErrorHandler \n");
            textArea.appendText("ioErrorHandler: " + event);
        }

    ]]>
   </fx:Script>

    <fx:Declarations>
        <s:HTTPService id="configurationService"
                   result="serviceResultHandler(event)" fault="servicefaultHandler(event)"/>
    </fx:Declarations>

    <s:Button label="High Level" click="configHandler(event)"
          horizontalCenter="100" top="20" />
    <s:Button label="Low Level" click="config2Handler(event)"
          horizontalCenter="-100" top="20"/>
    <s:TextArea id="textArea"
            left="20" right="20" top="{configButton.y + configButton.height + 20}" bottom="20"/>
</s:View>

Flash Builder模拟器上的结果

  • 当按下“低级别”按钮(URL Loader)时,文本区域上的文本为:

    Connecting to server using a low level component
    ...
    Entering openHandler 
    openHandler: [Event type="open" bubbles=false cancelable=false eventPhase=2] 
    Entering httpStatusHandler 
    httpStatusHandler: [HTTPStatusEvent type="httpStatus" bubbles=false cancelable=false eventPhase=2    status=401 responseURL=null] 
    Entering ioErrorHandler 
    ioErrorHandler: [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error  #2032: Stream Error. URL: http://10.0.0.221/api/v1/room/current/" errorID=2032]
    
  • 当按下“高级别”按钮(HTTPService)时,文本区域上的文本为:

    Connecting to server using a high level component 
    ... 
    Entering servicefaultHandler
    HTTP status code is: 401
    

Android设备上的搜索结果

  • 当按下“低级别”按钮(URL Loader)时,文本区域上的文本为:

    Connecting to server using a low level component 
    ... 
    Entering openHandler 
    openHandler: [Event type="open" bubbles=false cancelable=false eventPhase=2] 
    Entering httpStatusHandler 
    httpStatusHandler: [HTTPStatusEvent type="httpStatus" bubbles=false cancelable=false eventPhase=2    status=401 redirected=false responseURL=null] 
    Entering completeHandler 
    completeHandler: 
    
  • 当按下“高级别”按钮(HTTPService)时,文本区域上的文本为:

    Connecting to server using a high level component 
    ... 
    Entering serviceResultHandler
    HTTP status code is: 401
    

当我在Flash Builder的模拟器上运行应用程序时,两个组件都按预期工作,这意味着他们调度了FaultEvent和IOErrorEvent。在Android设备上,每个组件都行为不端,第一个调度ResultEvent,第二个调度Event.COMPLETE事件。

请注意,在这两种情况下,两个组件都会使用正确的HTTP状态代码。

我认为运行时存在问题,对吧?我很感激你对此事的评论。

1 个答案:

答案 0 :(得分:0)

我认为这里有一些误解可以先解决:

ResultEvent means "HTTPService call returns successfully."但在这个意义上的成功意味着我们设法实现连接并获得响应。

服务器响应任何HTTP状态代码完全有效,在本例中为Status 401 - Unauthorized,表示您已到达服务器但尝试访问您没有权限的位置。

FaultEvent means "HTTPService call fails"。但这里的失败不是建立连接或没有收到响应。

更多FaultEventFault错误类的事件包装器,它“表示远程过程调用(RPC)服务调用中的错误”。最常见的变体是IOError #2032: Stream Error,因其模棱两可而臭名昭着。

现在了解调试器和已发布版本之间的不同行为:

Capabilities.isDebugger为真时,Flash会以不同方式处理错误。一个documented example正在打开一个错误发生的对话框。

这是猜测,因为我找不到任何文档,但我发现HTTPServiceResultEvent : 401更改为FaultEvent : 401(因此将其转换为{{1}并不会让我感到惊讶错误)利用调试错误对话框。