2

I am clear about how to use HTTP Service in flex but i want to separate the functionality of calling service and getting response of the service in a different ActionScript class. So does anyone know how can i return the response of the HTTP service in flex ?

for e.g.

IN UTILITY class i want to have one method to which i will give one URL and it will give me the data obtained from that location. That's it. consider the following code snippet. reference code taken from could not be able to create http service programmitically in flex

        private function callService():void
        {
            var requestObj:Object = {};
            requestObj.q = cityName.text.toString();
            requestObj.format = FORMAT;
            requestObj.num_of_days = cNUMBER_OF_DAYS;
            requestObj.key = API_KEY;

            var weatherService:HTTPService = new HTTPService();
            weatherService.url = BASE_URL;
            weatherService.resultFormat = "object";
            weatherService.showBusyCursor = true;
            weatherService.request = requestObj;
            weatherService.addEventListener(ResultEvent.RESULT , weatherService_resultHandler);
            weatherService.addEventListener(FaultEvent.FAULT, weatherService_faultHandler);
            weatherService.send();
        }

        protected function weatherService_resultHandler(event:ResultEvent):void
        {
            trace("got result");
            **//WANT TO GIVE THIS RESULT BACK TO THE CALLER. SINCE RETURN TYPE OF 
            //METHOD IS VOID I CANNOT RETURN ANYTHING FROM HERE. HOW TO MAKE THIS
            //METHOD TO RETURN DATA?**
        }

        protected function weatherService_faultHandler(event:FaultEvent):void
        {
            trace("got fault");
        }
Community
  • 1
  • 1
ATR
  • 2,160
  • 4
  • 22
  • 43

1 Answers1

3

There are several solutions depending on the architecture of your project. The main idea is to fire the event (or call callback) when service receive response and handle it in the caller. The simplest way in your example is to return the weatherService object in the callService method and add the same listeners in the caller (ResultEvent.RESULT and FaultEvent.FAULT). The minus of this solution is that you have to parse the raw server response in caller rather than to work with some parsed value objects but as I noticed all depends on your project data flow.

UPD: the example of callback usage:

//map for storing the {service:callback} linkage
private var callbacks:Dictionary = new Dictionary(true);
/*
callback is a function like: function(success:Boolean, data:Object):void
*/
private function callService(callback:Function):void
{
    var requestObj:Object = {};
    requestObj.q = cityName.text.toString();
    requestObj.format = FORMAT;
    requestObj.num_of_days = cNUMBER_OF_DAYS;
    requestObj.key = API_KEY;

    var weatherService:HTTPService = new HTTPService();
    weatherService.resultFormat = "object";
    weatherService.showBusyCursor = true;
    weatherService.request = requestObj;
    weatherService.addEventListener(ResultEvent.RESULT, weatherService_handler);
    weatherService.addEventListener(FaultEvent.FAULT, weatherService_handler);
    var token:AsyncToken = weatherService.send();

    var obj:Object = {callback:callback, service:weatherService};
    callbacks[token.message.messageId] = obj;
}

protected function weatherService_handler(event:Event):void
{
    var success:Boolean = event.type == ResultEvent.RESULT;
    var token:AsyncToken = success ? ResultEvent(event).token : FaultEvent(event).token;

    var obj:Object = callbacks[token.message.messageId]
    var service:HTTPService = obj.service;
    service.removeEventListener(ResultEvent.RESULT , weatherService_handler);
    service.removeEventListener(FaultEvent.FAULT, weatherService_handler);

    var data:Object = success ? ResultEvent(event).result : FaultEvent(event).fault;
    var callback:Function = obj.callback;
    delete callbacks[event.target];

    callback(success, data);
}
fsbmain
  • 5,267
  • 2
  • 16
  • 23
  • Thanks for the reply. But with your solution also my problem will remain. I want completely decoupled class where i just have to give the method the url (along with other information if there are any ) from which it has to fetch the data and the method will be returning me just the response, nothing else. If i will return the weatherService object then i will have to write handlers at the caller side which is not i want to do. Can you give me hint on another solutions that you are having. – ATR Jan 15 '13 at 10:53
  • 1
    In your case the simplest way to completely decoupled callers and service class is to create the custom event i.e. _ServiceEvent_ with fields like _data:String_ and types _DATA_ and _ERROR_ but this solution has a lack of simultaneous request (for example if you call _callService_ from to different callers the second caller will be triggered with data from first one). This ussie cal be solved by passing the callback object/method from the caller to the _callService_ or creating separate request service for each request) – fsbmain Jan 15 '13 at 11:44
  • can you give any code example/documentation/tutorial explaining what you are saying because i am not that familiar with flex so that i can understand what are you trying to say. – ATR Jan 15 '13 at 12:02
  • Thanks. I really appreciate your help. why you have created "callback" of type Dictionary over here ? In callservice method what requestObj is doing exactly ? in weatherService_handler method i am getting very little understanding of the code. and why you have commented out the second line of code. I think it may be by mistake right? It would be really helpful if you can give some explanation to the code. – ATR Jan 15 '13 at 13:39
  • 1
    I added a couple of comments and fix one mistake (forget to save the callback function in the callbacks map). I added the _callbacks_ map to store the reference to the callback function passed to the _callService_ method. It's a type of Dictionary because of the ability to use _weatherService_ as the key. With this code you can call the _callService_ from the different callers, you can also add other parameters to the _callService_ method for the custom service requests. – fsbmain Jan 15 '13 at 14:03
  • "Implicit coercion of a value with static type Object to a possibly unrelated type mx.rpc.http:HTTPService." I get this error in weatherService_handler function at first line. – ATR Jan 15 '13 at 14:23
  • "var service:HTTPService = event.target as HTTPService". After execution of this line also service remains null and execution gives me null reference error in the next line while removing event handler. so i guess there is something problem with event.target. – ATR Jan 16 '13 at 04:08
  • It's very strange, event.target can't be none but HTTPService and this code works fine for me with test server url. – fsbmain Jan 16 '13 at 10:21
  • while i debug i see that the type of event.target is HttpOperation. – ATR Jan 16 '13 at 10:25
  • i have commented out "requestObj" in the code and some parameters of the service which are "resultFormat", "showBusyCursor" and "request". Can it cause any problem ? – ATR Jan 16 '13 at 10:30
  • Yes, you are right about the type of event.target, my test hasn't shown that. I updated the code, now we store the link to the service object in the map storage. You can use this storage for other parameters you want to pass to the service handler as well. – fsbmain Jan 16 '13 at 10:50