That the comms are handled asynchronously is entirely distinct from the user experience being asynchronous.
Think of how many apps on you iPhone etc when you start them dont popup instantly or when you want to do something they put up a spinner until something has occurred because they require you to log in etc.
Your UI doesn’t have to appear to be async just because the comms are being done async
I don’t want to disagree with anything here, but just to add another perspective, having an async experience can fit in nicely with how users expect mobile apps to work.
In my case I have 7 services that need to complete one after the other before a user is able to use my app fully. First the user must be authenticated, then I need to get their permissions, then their available datasets, then other members of the dataset that they can assign to things, then I need a bunch of GUIDs for new records (our services like to issue GUIDs in a particular way to make sorting more efficient in our n-tier database), then I need to check the notifications that have occurred since I was last online and update cached data, then I need to get the tombstones to delete records from the cache that were removed since I was last online…and after all that we’re good to go.
To do all of this can take 20 or 30 seconds on a slow connection (but usually only takes about 10 to 15 seconds in my testing) so having it happen asynchronously is actually really useful. My app is fully responsive from startup but some things, such as adding new records for example, aren’t available until the required services have returned. But most users aren’t aware of this because by the time they tap on the thing that they are looking for and find it (local data is cached) the app is all setup and ready to go.
@Jason Tait - you have a similar user experience to what I’ve got going on, at least in some respects. One of the features of my app is that it will synchronize its data with the cloud database, both pulling new records down from and pushing new records up to the cloud. This requires a potentially lengthy conversation with the REST API, and I can’t just say “Whoa there pardner! We’re synching here… everybody else pause for a bit!”… it all needs to happen in the background, and is mostly completely transparent to the user, except that there is a small “Synchronizing…” label that appears out of the way at the bottom corner of their screen while it is actively running, then disappears once it is done.
So, Norm is right - the UI is distinct from the comms, and I can elect to either make the user wait or allow them to keep working when comms are happening, depending on the work the comms are doing.
One other thing I’ve just run into: It appears that I can’t issue a new socket operation from within a pageReceived event. Trying to do so results in a “Socket in use” error.
So, the suggestions that I use a socket like this appear to be mostly impossible:
Send–>pageReceived (which decides that the data received means we need to send another message, so…)–>Send
It looks like I have to wait until the stack has returned completely from pageReceived before I can make a new request on the same socket. Is this true?
EDIT: pageReceived, not dataAvailable - I’m using xojo.net.httpSocket.
Its been a long time since XDC
But we have this sort of thing go on in the back ground there
No you cant issue a new command on the same socket - it IS still busy
Dont recall off the top of my head what we did but i’ll peek when I have a moment
@Kimball Larsen in case in helps, the way I get around this issue is to not reuse the HTTPSocket. My API class is based on an HTTPSocket, and I create a new API instance for each service call that my app does. Most times, because things are executing asynchronously, this is desirable as you can get a couple of things going at the same time/as you need them. On the occasions when I need the services to be more like synchronous services - which is really just for my app startup process - as each service completes I have it call the next one; so the authentication service instantiates a new API/Socket object as it completes and calls the user service, etc. The sockets destroy themselves once they finish executing.