I'm developing a Flex application and am having some trouble working with asynchronous calls. This is what I would like to be able do:
[Bindable] var fooTypes : ArrayCollection();
for each (var fooType : FooType in getFooTypes()) {
fooType.fooCount = getFooCountForType(fooType);
itemTypes.addItem(fooType);
}
The issue I'm running into is that both getFooTypes and getFooCountForType are asynchronous calls to a web service. I understand how to populate fooTypes by setting a Responder and using ResultEvent, but how can I call another service using the result? Are there any suggestions/patterns/frameworks for handling this?
If possible, I Strongly recommed re-working your remote services to return all the data you need in one swoop.
But, if you do not feel that is possible or practical for whatever reason, I would recommend doing some type of remote call chaining.
Add all the "remote calls" you want to make in array. Call the first one. In the result handler process the results and then pop the next one and call it.
I'm a bit unclear from your code sample when you are calling the remote call, but I assume it part of the getFooCountForType method. Conceptually I would do something like this. Define the array of calls to make:
public var callsToMake : Array = new Array();
cache the currently in process fooType:
public var fooType : FooType;
Do your loop and store the results:
for each (var fooType : FooType in getFooTypes()) {
callsToMake.push(fooType);
// based on your code sample I'm unclear if adding the fooTypes to itemTypes is best done here or in the result handler
itemTypes.addItem(fooType);
}
Then call the remote handler and save the foo you're processing:
fooType = callsToMake.pop();
getFooCountForType(fooTypeToProcess);
In the result handler do something like this:
// process results, possibly by setting
fooType.fooCount = results.someResult;
and call the remote method again:
fooType = callsToMake.pop();
getFooCountForType(fooTypeToProcess);
Related
I have a method in .NET (GetDataStationParts), which I declare with 2 parameters, I want to call it from a JavaScript, and I use the InvokeMethodAsyn function in this way:
const { data } = require("jquery");
function GetParteScrap()
{
var idestacionjs = document.getElementById('getestacion');
var idmodelojs = document.getElementById('getmodelo');
var tablascrap = DotNet.InvokeMethodAsyn("YMMScrapSystem", "GetDataStationParts", idestacionjs, idmodelojs);
console.log(tablascrap);
}
To do it, I base it on an example on the web but I'm not sure where it gets the DotNet object to then invoke the method, the intention of my code is that after selecting parameters of 2 , go to the database and execute a SQL-level function, which will return a table, with the function GetDataStationParts, I try to give it the functionality to execute my method at the DB level as follows
[JSInvokable]
public async Task<IEnumerable<GetEstacionParte>>GetDataStationParts(int modelo, int estacion)
{
var resul = await _context.Set<GetEstacionParte>().FromSqlInterpolated($"SELECT * FROM dbo.GetEstacionParte({modelo},{estacion})").ToArrayAsync();
return resul;
}
The SQL level function works correctly, but when running the application at the console level in the browser, it throws the following error, where it indicates that the function is not defined
Where could the error be? Thank you for reading
require() is not a feature that is built into the browser. Javascript environment does not understand how to handle require(), In Node.js by Default this function is available.
I suspect you most probably missing some reference here. You can either download require.js from here & link with your application or use below script tag.
<script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>
In my attempt to learn flex remoting I came across this
flexService.getRules.addEventListener(ResultEvent.RESULT, loadRules);
here flexService is a remote java object .. In above function call can any one help me that when ResultEvent.RESULT will occur. On studying about ResultEvent in AS document it states as
The event that indicates an RPC operation has successfully returned a result
So keeping that in mind my guess is ResultEvent will be fired when flexService.getRules method will successfully return a list of object,where flexService is object of remote class FlexService having getRules function which returns list of object, Can any one please tell how exactly it works..
Also can some one plz tell me how eventListener can be added to a list of object
PS: I am using Spring as backend
Here you set result to arraycollection
private function loadRules(event:ResultEvent):void
{
var list:ArrayCollection = new ArrayCollection();
list = event.result as ArrayCollection;
}
I'll be going on assumptions since you apparently aren't keen on showing more code or giving pertinent information.
I'm assuming that 'flexService' is a RemoteObject that has set all required properties (destination, endpoint, etc)
I'm assuming that 'getRules' is an available function on your java remote class which returns the information needed.
I'm assuming that everything is being sent over using AMF.
in that case, it's as simple as doing this:
var token:ASyncToken = flexService.getRules(arg1, arg2);
token.addResponder(new Responder(yourResultFunction, yourFaultFunction));
private function yourResultFunction(data:Object):void
{
// Do something with data here
}
private function yourFaultFunction(fault:Object):void
{
// do something if a fault happens
}
Of course, this is very basic and you should try to implement a better pattern (commands) around it.
I have some questions with a particular structure of a program I'm writing.
I'm using a Remote Object to make a remote call to a Rails method (using WebOrb). The problem arises in the way that I get my data back.
Basically I have a function, getConditions, in which I add an event listener to my remote call and then I make the remote call. However, what I want to do is to get that data back in getConditions so I can return it. This is a problem because I only access the event result data in the event handler. Here's some basic code describing this issue:
public function getConditions():Array
{
remoteObject.getConditions.addEventListener("result", onConditionResult);
remoteObject.getConditions();
//Here is where I want to get my event.result data back
}
public function onConditionResult(event:ResultEvent):void
{
//Here's the data that I want
event.result;
}
How can I achieve this data turn-about?
Remote calls in flex are always asynchronous so you won't be able to call getConditions() and wait there for the result. You have to use a function closure to process the results, either by means of an event handler than you declare elsewhere or a dynamic one created immediately within getConditions(), like so:
remoteObject.getConditions.addEventListener("result", function(event:ResultEvent):void {
// Run the code that you would want to when process the result.
});
remoteObject.getConditions();
The advantage of doing the above is that you would be able to "see" parameters passed to getConditions() or the result of any logic that happened before addEventListener() in the function closure. This however, takes a slight performance hit compared to declaring an explicit function (for that exact reason).
I should also add that doing so requires you to clean up after yourselves to make sure that you are not creating a new listener for every request.
you do it like this
public function getConditions():Array
{
remoteObject.getConditions.addEventListener("result", onConditionResult);
remoteObject.getConditions();
}
public function callMyExtraFunction(data:Object):void
{
//Here is where you want to get your event.result data back
}
public function onConditionResult(event:ResultEvent):void
{
//Here's the data that you want
var data:Object = event.result;
callMyExtraFunction(data);
}
You could make use of Call Responder like so :
<s:CallResponder id="getOperationsResult"/>
then use these lines to get the result from get operations
getOperationResult.token = remoteObject.getOperation();
this creates the call and returns the result stores it in getOpresult
whnever u want to access this u can call that token or getOperationResult.lastResult
Hope that helps
Chris
Im trying to connect a Flash client to BlazeDS. There has been some success with this from others using the vanilla BlazeDS setup. However I'm using the new Spring BlazeDS Integration from springsource and running aground.
The flash client actually seems to be working in that I can see the correct data in the body of the returned object, but for some reason unknown it fails casting as an IMessage. It fails in PollingChannel.as on this line with the subject line error
var messageList:Array = msg.body as Array;
for each (var message:IMessage in messageList) <--
On application load I register a whole bunch of classes like so
registerClassAlias( "flex.messaging.messages.RemotingMessage", RemotingMessage );
registerClassAlias("mx.messaging.messages.IMessage", IMessage);
etc..
my code is basically
var channelSet:mx.messaging.ChannelSet = new mx.messaging.ChannelSet();
var channel:mx.messaging.channels.AMFChannel = new AMFChannel("my-amf", "http://localhost:8400/SpringA/messagebroker/amf");
channelSet.addChannel(channel);
var consumer:mx.messaging.Consumer = new Consumer();
consumer.channelSet = channelSet;
consumer.destination = "simple-feed";
consumer.subscribe();
consumer.addEventListener(MessageEvent.MESSAGE, test);
private function test(event:IMessage)
{
trace("msg..");
// breakpoint never makes it here
}
I have a flex client which works 100% with same destination/channel.
The error in the title means that you, for some reason, got an object that is not implementing or extending the IMessage interface, therefore the loop can not cast it in this part:
for each (var message:IMessage in messageList){
Either you should somehow make sure that you don't add anything that is not extending or implementing IMessage, or check if the variable IS actually ext./imp. it. Also - if you want to do that, you will have to change the for each like this:
for each (var obj in messageList){
if (obj is IMessage){
var message:IMessage = obj as IMessage;
// DO STUFF HERE
}
}
Add this Object mapping:
registerClassAlias("flex.messaging.io.ObjectProxy", ObjectProxy);
If on your Java VO objects you have overridden the hashcode() method, this situation could happen.
Remove the hashcode() override (if you are able to).
See my blog for the backstory on how I discovered this. http://squaredi.blogspot.com/2013/12/remoting-landmine-without-stack-trace.html
I had the same error when trying to send an actionscript object to the backend. My problem was that my c# equivalent object was missing an public parameterless constructor.
If I want to call a server function from JavaScript to retrieve a name of a person from a database (just as an example)... and I went...
name = myServices.getName(userId);
If I have a script manager with a service reference to a .asmx file that has the web method getName( int userId ) {} then this function should be called properly and would, eventually, return the name for that userId.
Unfortunately, I want to do...
name = myServices.getName(userId);
alert(name);
however, when doing ASP.NET AJAX, it would call the web method and continue executing before waiting for a response from the server (which I understand is the point of AJAX, to stop the browser from freezing while waiting for data)
I need to get the name back from the server before I can continue executing... How can I approach this to fix this issue?
There is a method you can add as a parameter to the service method that will call the method on success where you can do other stuff.
For example:
function test() {
PageMethods.MyMethod("name", OnMyMethodComplete);
}
function OnMyMethodComplete(result, userContext, methodName) {
alert(result);
}
If you want to call a Web method synchronously, you'll need to set up the request manually and use a Sys.Net.XMLHttpSyncExecutor.
Here's an example (see ExecuteSynchronously function).
For a JavaScript solution, you could loop until name has a value. Adjust time-based on latency to keep app responsive
var time = 100;
window.setTimeout(name == '' ? wait : continue, time);
function wait() {
window.setTimeout(name == '' ? wait : continue, time);
}
function continue() {
//code having to do with name
alert(name);
}
Congratulations! You've taken your first step into a larger asynchronous world. I'd definitely go with using the callbacks that CSharpAtl suggested.