I have a couple of remote object methods that I want to respond to in different ways depending on the context, but I'd rather not set up a bunch of different RemoteObject aliases. Any advice on doing that? Some background:
Let's say I have an admin application that displays sales stats in different ways. The remote method looks like:
<mx:RemoteObject id="rpt" destination="AMFServer">
<mx:method name="getSalesStats" fault="getSalesStatsFault(event)"
result = "getSalesStatsSuccess(event)" />
</mx:RemoteObject>
The getSalesStats method takes an employee ID and a sales type as its arguments. You'd call it like:
rpt.getSalesStats(120, "peanuts");
public function getSalesStatsSuccess(e:ResultEvent):void {
salesdata:ArrayCollection = e.result.rows as ArrayCollection;
salesGraph.dataProvider = salesdata;
salesGraphPanel.title = "Peanut Sales, 1990";
}
I want to be able to call this method in different contexts, sometimes sending the result to a chart and sometimes to a datagrid; I want to be able to change the title and type of chart depending on what the user wants. Some of what I want can be achieved by evaluating the data returned from the server; the object contains the report name, so I can evaluate that value. But some things need to change based on more than just what I get back from the server. If this was a synchronous call, it would be easy; I'd do something like:
function buttonOneClick():void {
myData1:ArrayCollection = getSalesStats(120, "peanuts");
myChart.dataProvider = myData1;
}
function buttonTwoClick():void {
myData2:ArrayCollection = getSalesStats(120, "cashews");
myDataGrid.dataProvider = myData2;
}
I'd like to pass something through the remote method to the responding function, like:
rpt.getSalesStats(120, "peanuts", "clicked button one");
but that of course throws an error because the server doesn't want that last argument. Any thoughts? I'll clarify if this is confusing..
Here is a great example of using AsyncToken with RemoteObject method calls to do precisely what you need.
Something to keep in mind when you are using AsyncToken is that it is a dynamic object and you can add any property you'd like to it. The event in your responder method will carry a reference to the AsyncToken and you can access your dynamic properties to easily identify the context of the response.
In Flex 4 and 3.4, use the CallResponder class:
<mx:RemoteObject id="rpt" destination="AMFServer"/>
<s:CallResponder id="toChartResponder" fault="getSalesStatsFault(event)"
result = "getSalesStatsToChartSuccess(event)" />
<s:CallResponder id="toDataGridResponder"fault="getSalesStatsFault(event)"
result = "getSalesStatsToDataGridSuccess(event)"/>
To make the call, assign the returned AsyncToken from the method call to the token property of the responder:
toDataGridResponder.token = rpt.getSalesStats();
This separates the response definition from the method call, and you can then wrap it in whatever logic you need.
You can have multiple methods to a remoteObject.
<mx:RemoteObject id="rpt" destination="AMFServer">
<mx:method name="getSalesStatsToChart" fault="getSalesStatsFault(event)"
result = "getSalesStatsToChartSuccess(event)" />
<mx:method name="getSalesStatsToDataGrid" fault="getSalesStatsFault(event)"
result = "getSalesStatsToDataGridSuccess(event)" />
</mx:RemoteObject>
Is there any reason why you can't use something like this?
Flex supports the Asynchronous Completion Token design pattern for handling multiple requests to the same service. See the BlazeDS documentation.
I think there are only two ways to do this:
- Have a separate remote object for each call context. The effect on performance is neglectable IMO.
- Set concurrency for the remoteobject to single (or first, not sure about the name, but not multiple or last) and have some sort of flag that you can use to tell which was the last method called. This will, of course, limit server calls to one at a time on this remote object. calls will fail immediately if the previous call didn't return a result yet.
That's the only way I see it if you have no access to the server. If I were in your situation, i will even create the remote object every time I do the remote call. I don't think it affects performance (please correct me if I'm wrong). Good luck!
var rpcCall:AsyncToken;
rpcCall = remoteService.getSessionId();
rpcCall.addResponder(new Responder(handler_getSessionIdSuccess, handler_getSessionIdFault) );
rpcCall = remoteService.getMyData();
rpcCall.addResponder(new Responder(handler_getMyDataSuccess, handlerfault));
"remoteService" instance of remoteobject
Hope it will make sense.