异步网络调用

Asynchronous network calls

本文关键字:调用 网络 异步      更新时间:2023-10-16

我创建了一个具有异步OpenWebPage()函数的类。一旦调用OpenWebPage(someUrl),就会调用一个处理程序- OnPageLoad(reply)。我一直在使用一个名为lastAction的全局变量来处理页面加载后的东西-处理程序检查lastAction是什么并调用适当的函数。例如:

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
     }
}

现在,当我们有大量的"动作"时,这是相当难以编写和跟踪的。当我用Python(同步)做事情时,它要简单得多,比如:

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

想象一下,现在我有一个队列类,其中包含操作:主页、登录、新主题。我应该如何通过异步回调执行所有这些操作(以适当的顺序,一个接一个!)?第一个例子显然是完全硬编码的。

我希望你能理解我的问题,因为坦率地说,我担心这是有史以来最糟糕的问题:x

注:

如果您尝试使用单个成员变量来维护任意数量的异步操作的状态,就会招来各种各样的bug,正如您在上面描述的那样。您无法确定OpenWebPage调用完成的顺序,因此也无法将lastAction在任何给定时间的值与任何特定操作关联起来。

有很多方法可以解决这个问题,例如:

  1. 将网页加载封装在一个不可变的类中,每个实例处理一个页面
  2. OpenWebPage返回一个对象,用于跟踪进程并存储操作状态
  3. 在操作完成时触发一个信号,并将操作的上下文附加到信号

您需要在每个"if"分支的末尾添加"return"语句:在您的代码中,所有"if"分支都在第一次OnPageLoad调用中执行。

一般来说,异步状态管理总是比同步状态管理更复杂。考虑用枚举类型替换lastAction类型。此外,如果OnPageLoad线程上下文是任意的,则需要同步访问全局变量。