Does anyone know of any good resources that fully explain how functions and results will fire in an Adobe AIR app where multiple things are happening at once?
As a simple test, I've created a single service that I just keep changing the url of, then issuing a send(). It seems that no matter how many send() calls I put in, all of these get executed before the 'result' eventListener function gets called for the first time.
Is this how it works? i.e. the current function gets fully executed, with the async returns queueing up to be processed after AIR has finished what it's currently doing.
Likewise, if the user does something while all this is going on, I presume their request goes to the back of the queue as well?
All that makes sense, but I'm just wondering if it's documented anywhere.
While I'm on one, is it recommended practice to reuse the same HTTPService in this way, or is it better to create one for each concurrent transaction? Just because it works, doesn't mean it's the right thing to do...
I'm not aware of any documentation that explains this, but I can confirm that code blocks get executed before async calls are made, or at least before their result is being processed. If it didn't work that way, you would for instance not always be able to attach a responder to a token of a service call, because the result might already have been processed.
var token:AsyncToken = myService.someMethod();
token.addResponder(new Responder(resultHandler, faultHandler));
Developers coming from other platforms find this strange as they would expect the assignment of the responder to be too late.
So while I don't have an official explanation about the technical details inside the Flash Player, I can assure that it works this way.
If the user does something while a call is pending, the new request will indeed just be added as a new asynchronous call. Note that we can't realy speak of a queue, as there is no guarantee that the response of the first call comes in before the response of the second call. This depends on how much time the actual requests take.
You can perfectly reuse an HTTPService instance.
PS: Based on this, we were able to build the Operation API in Spring ActionScript. It is basically an API that allows you to execute asynchronous processes in a uniform way, without having to worry about the details of the actual async process.
The following code executes an async process and attaches a handler to it. This is also something that puzzles many developers at first, for reasons similar to the asyncToken situation.
var operation:IOperation = doSomeOperation();
operation.addCompleteListener(aCompleteHandler);
operation.addErrorListener(anErrorHandler);
Related
I am writing an app that makes plenty of network requests. As usual they are
async, i.e. the call of the request method returns immediately and the result
is delivered via a delegate method or in a closure after some delay.
Now on my registration screen I sent a register request to my backend and
want to verify that the success UI is shown when the request finishes.
Which options are out there to wait for the request to finish, verify the
success UI and only after that leave the test method?
Also are there any more clever options than waiting for the request to finish?
Thanks in advance!
Trivial Approach
Apple implemented major improvements in Xcode 9 / iOS 11 that enables you to wait for the appearance of a UI element. You can use the following one-liner:
<#yourElement#>.waitForExistence(timeout: 5)
Advanced Approach
In general UI and unit tests (referred to as tests here) must run as fast as possible so the developer can run them often and does not get frustrated by the need to run a slow test suite multiple times a day. In some cases, there is the possibility that an (internal or security-related) app accesses an API that can only be accessed from certain networks / IP ranges / hosts. Also, most CI services offer pretty bad hardware and limited internet-connection speed.
For all of those reasons, it is recommended to implement tests in a way that they do no real network requests. Instead, they are run with fake data, so-called fixtures. A clever developer realizes this test suite in a way that source of the data can be switched using a simple switch like a boolean property. Additionally, when the switch is set to fetch real backend data the fixtures can be refreshed/recorded from the backend automatically. This way it is pretty easy to update the fake data and quickly detect changes of the API.
But the main advantage of this approach is speed. Your test will not make real network requests but instead run against local data what makes them independent on:
server issues
connection speed
network restrictions
This way you can run your tests very fast and thus much more often - which is a good way of writing code ("Test Driven Development").
On the other hand, you won't detect server changes immediately anymore since the fake data won't change when the backend data changes. But this is solved by simply refreshing your fixtures using the switch you have implemented because you are a smart developer which makes this issue a story you can tell your children!
But wait, I forgot something! Why this is a replacement for the trivial approach above - you ask? Simple! Since you use local data which is available immediately you also can call the completion handler immediately too. So there is no delay between doing the request and verifying your success UI. This means you don't need to wait which makes your tests even faster!
I hope this helps some of my fellows out there. If you need more guidance regarding this topic don't hesitate and reply to this post.
Cya!
Problem
I'm currently grabbing weather forecast information with [NSData dataWithContentsOfURL: url]. The problem with this is that if there are errors during the URL fetch, I just get back a nil.
An alternative to the method [NSData dataWithContentsOfURL:options:error:] will provide error info to me, but what my calling function wants is the data, not a possible error that it must diagnose and deal with.
Requirements
What I'd like is a single function that a client can call to grab a URL that "absolutely will not stop" until the URL has been loaded.
I don't want the function's clients to need to think about:
Timeouts.
Internet connections being unavailable or not.
The device being locked or the app moving in to the background.
The actual site in question being down.
Other sources of error.
Other design objectives
The function should treat the device and remote site nicely – it should not swamp it with requests resends that will certainly fail, for example.
The caller should be able to abort the attempt if it desires, so it'll want to have a handle to the request allowing it to kill it off.
The function should be asynchronous, taking a block to handle the result when it eventually arrives.
For extra marks a method for the calling function to be sent error diagnostics would be nice. Again, I think a block would work nicely for this. The needn't do anything about the error, because the function isn't going to give up, but it can use it to provide useful feedback to a user. For example, to allay their concerns, or prompt them to take remedial action (turn networking back on, for example).
Possible interface
So the a client call to the function might go like this:
_currentGrabber = [TenaciousURLGrabber
grabberForURL: myURL
withCompletionAndDiagnosticsHandler:
^(NSData* finalData, ErrorObject *error){
if(data)
{
// Update my UI using data.
}
else
{
// Update my UI to show `[error localisedError];`
}
}];
If the client gets bored or decides that the fetch isn't worth it any more, it can do:
[_currentGrabber invalidate];
Implementation thoughts.
It'd be great if this pretty much already exists. Otherwise, I'm interested in suggestions on implementing this functionality.
I should probably be making use of NSURLSession instead of the older NSURLConnection. The possibility of background (out of process) downloads looks useful? Any tips beyond this?
The function should use SCNetworkReachability as demonstrated in the Reachability sample application following failure to determine when its worth a retry attempt.
Here is a simple question.
suppose that I have a very long loop to execute, It would be nice to keep the user informed about the progressing right? I would print for example the number of loops that have been executed so far and how many are remaining.
The problem that I have is those output wouldn't be visualized until the the loop is finished, and thus there will be no point for them to be displayed.
I'm sure that there is some method in dart that can some sort of a handler to the browser to execute tasks and events whenever I want to and keep running the loop.
I'm new to dart, I hope that someone could answer this question.
Thank you.
PS: If you don't know how to, you can give me any ideas of keywords that I can use to look for this particular feature in dart documentation, it will be very helpful.
You can dig into Isolates, which allow background work on supported browsers.
https://api.dartlang.org/docs/channels/stable/latest/dart_isolate.html
Nothing as simple as DoEvents(), but all of the pieces are there.
I think too that Isolates are the best approach but wasn't successful using them on the browser a while ago, but there was a bigger refactoring going on lately in Isolates.
Does anyone know of a current client side Isolates example?
The API doc referenced by #kevmoo contains a link to an Isolates article that doesn't exist anymore (maybe must be rewritten due to the mentioned refactoring).
Another approach would be a method that returns after a chunk of work and gets recalled repeated in a loop until it returns for example true for done (false for not yet).
When you call this method using scheduleMicrotask(doChunk) or new Timer(() => doChunk()) other tasks get some air (import 'dart:async';) each time before the method gets actually called.
My app includes a back-end server, with many transactions which must be carried out in the background. Many of these transactions require many synchronous bits of code to run.
For example, do a query, use the result to do another query, create a new back-end object, then return a reference to the new object to a view controller object in the foreground so that the UI can be updated.
A more specific scenario would be to carry out a sequence of AJAX calls in order, similar to this question, but in iOS.
This sequence of tasks is really one unified piece of work. I did not find existing facilities in iOS that allowed me to cleanly code this sequence as a "unit of work". Likewise I did not see a way to provide a consistent context for the "unit of work" that would be available across the sequence of async tasks.
I recently had to do some JavaScript and had to learn to use the Promise concept that is common in JS. I realized that I could adapt this idea to iOS and objective-C. The results are here on Github. There is documentation, code and unit tests.
A Promise should be thought of as a promise to return a result object (id) or an error object (NSError) to a block at a future time. A Promise object is created to represent the asynchronous result. The asynchronous code delivers the result to the Promise and then the Promise schedules and runs a block to handle the result or error.
If you are familiar with Promises on JS, you will recognize the iOS version immediately. If not, check out the Readme and the Reference.
I've used most of the usual suspects, and I have to say that for me, Grand Central Dispatch is the way to go.
Apple obviously care enough about it to re-write a lot of their library code to use completion blocks.
IIRC, Apple have also said that GCD is the preferred implementation for multitasking.
I also remember that some of the previous options have been re-implemented using GCD under the hood, so you're not already attached to something else, Go GCD!
BTW, I used to find writing the block signatures a real pain, but if you just hit return when the placeholder is selected, it does all that for you. What could be sweeter than that.
I have not been able to find a way to cancel/terminate asynchronous read operation after successful HttpWebRequest. There is no way to set timeout, ThreadPool.RegisterWaitForSingleObject is not working too. And closing the underlying socket is not an option too because neither HttpWebRequest/Reponse provide access to it.
Edit:
Sadly this approach that Sunny suggestet works only for HttpWebRequest.BeginGetResponse. For the stream that you get after GetResponseStream() for some reason RegisterWaitForSingleObject is not working - the callback is never called.
The situation is the following:
I got an application that uses HttpGetRequest. It is build by using the default MSDN example for async httpwebrequest. Getting response is working like a charm. But on rare occasions the server that my httpwebrequest is connecting to forgets to close the socket. So I am hung on a infinite read from BeginRead.
In some rare occasions the other server forget
Why not RegisterWaitForSingleObject? You can use it for time out, and in the handler you can call request.Abort().
Here's an example. Btw, I have used simial approach before I found this article in the past, and it worked like a charm.
NOTE: The real end of the operation will happen on the next Stream.Read (of only the request/response was async) or Stream.EndRead (if the reading is async as well). You still need to capture the exception thrown in the EndXXXX handler.
EDIT: If the RegisterWaitForSingleObject never get called, then you have another issue, which is most probably a ThreadPool having not enough free threads. The callback for RegisterWaitForSingle object is called on a ThreadPool thread, and if there is no a free thread in the pool, it will never get called. You have some solutions:
Make your pages asynchronous. Why? How.
Change the max threads in the pool.
In any case, increasing the pool size will not help you too much. You have to inspect your code for resource (stream) leaks, and make sure that you not only call request.Abort(), but also close the response. Make sure than in your callbacks you use the proper EndXXX method, etc.
I nazdrave :)