liliumdev
liliumdev

Reputation: 1179

Asynchronous network calls

I made a class that has an asynchronous OpenWebPage() function. Once you call OpenWebPage(someUrl), a handler gets called - OnPageLoad(reply). I have been using a global variable called lastAction to take care of stuff once a page is loaded - handler checks what is the lastAction and calls an appropriate function. For example:

this->lastAction == "homepage";
this->OpenWebPage("http://www.hardwarebase.net");

void OnPageLoad(reply)
{
     if(this->lastAction == "homepage")
     {
         this->lastAction = "login";
         this->Login();     // POSTs a form and OnPageLoad gets called again
     }
     else if(this->lastAction == "login")
     {
         this->PostLogin(); // Checks did we log in properly, sets lastAction as new topic and goes to new topic URL
     }
     else if(this->lastAction == "new topic")
     {
         this->WriteTopic(); // Does some more stuff ... you get the point
     }
}

Now, this is rather hard to write and keep track of when we have a large number of "actions". When I was doing stuff in Python (synchronously) it was much easier, like:

OpenWebPage("http://hardwarebase.net") // Stores the loaded page HTML in self.page
OpenWebpage("http://hardwarebase.net/login", {"user": username, "pw": password}) // POSTs a form
if(self.page == ...): // now do some more checks etc.
    // do something more

Imagine now that I have a queue class which holds the actions: homepage, login, new topic. How am I supposed to execute all those actions (in proper order, one after one!) via the asynchronous callback? The first example is totally hard-coded obviously.

I hope you understand my question, because frankly I fear this is the worst question ever written :x

P.S. All this is done in Qt.

Upvotes: 2

Views: 408

Answers (2)

Stu Mackellar
Stu Mackellar

Reputation: 11638

You are inviting all manner of bugs if you try and use a single member variable to maintain state for an arbitrary number of asynchronous operations, which is what you describe above. There is no way for you to determine the order that the OpenWebPage calls complete, so there's also no way to associate the value of lastAction at any given time with any specific operation.

There are a number of ways to solve this, e.g.:

  1. Encapsulate web page loading in an immutable class that processes one page per instance
  2. Return an object from OpenWebPage which tracks progress and stores the operation's state
  3. Fire a signal when an operation completes and attach the operation's context to the signal

Upvotes: 1

Alex F
Alex F

Reputation: 43331

You need to add "return" statement in the end of every "if" branch: in your code, all "if" branches are executed in the first OnPageLoad call.

Generally, asynchronous state mamangment is always more complicated that synchronous. Consider replacing lastAction type with enumeration. Also, if OnPageLoad thread context is arbitrary, you need to synchronize access to global variables.

Upvotes: 1

Related Questions