使用 QNetworkManager 在 QT 中设计多个嵌套的 GET/POST 的最佳方法
Posted
技术标签:
【中文标题】使用 QNetworkManager 在 QT 中设计多个嵌套的 GET/POST 的最佳方法【英文标题】:Best way to design multple and nested GET/POST in QT with QNetworkManager 【发布时间】:2016-09-02 06:40:15 【问题描述】:我的疑问是关于实现多个嵌套 GET/POST 请求的软件的正确设计。
假设您必须运行一个需要 GET 和一个 POST 的 login() 函数,然后运行需要两个 GET 的 retrieveXYZ()(依此类推,可扩展)。
我当时的想法是这样的
mainwindow.cpp
//code
login();
retrieveXYZ();
//code
Mainwindow::login()
//code
connect(nam, SIGNAL(finished()), this, SLOT(onGetLoginFinished()));
nam->get(...);
Mainwindow::onGetLoginFinished()
//do stuff
connect(nam, SIGNAL(finished()), this, SLOT(onPostLoginFinished()));
nam->post(...);
Mainwindow::onPostLoginFinished()
//do stuff
Mainwindow::retrieveXYZ()
//code
connect(nam, SIGNAL(finished()), this, SLOT(onGet1RetrieveFinished()));
nam->get();
//code
Mainwindow::onGet1RetrieveXYZFinished()
//do stuff
connect(nam, SIGNAL(finished()), this, SLOT(onGet2RetrieveFinished()));
nam->get();
或者我应该使用 QSignalMapper 之类的东西吗? 哪种是最正确/最有效的方法?我见过有人使用 sender() 演员,但我不明白这一点。
基本上我想检索特定的回复完成()信号,而不是一般的(或 qnam 的)信号
这种方法可能有效,但对我来说不是很好和干净
这是我们能得到的最好的吗?
http://www.johanpaul.com/blog/2011/07/why-qnetworkaccessmanager-should-not-have-the-finishedqnetworkreply-signal/
将连接方法移至回复?
【问题讨论】:
你有几个QNetworkAccessManager
吗?哪个部分是串行/并行的?
我只有一个QNetworkAccessManager,串口/并口是什么意思?我没有并行请求,我只有连续剧。问题是它们因任务而异。 Login() 函数是 GET 后跟 POST 的示例
所以你只想阻塞请求?
我希望根据我发出的请求类型和在哪个功能中执行不同的任务,而不是阻止...当我发出 GET 时,要使用的功能将根据我请求的条件而改变它
【参考方案1】:
我得到了类似的东西:
struct RequestResult
int httpCode;
QByteArray content;
;
RequestResult
ExecuteRequest(const std::function<QNetworkReply*(QNetworkAccessManager&)>& action,
const std::chrono::milliseconds& timeOut)
QEventLoop eLoop;
QTimer timeOutTimer;
QNetworkAccessManager nam;
QObject::connect(&timeOutTimer, &QTimer::timeout, &eLoop, &QEventLoop::quit);
QObject::connect(&nam, &QNetworkAccessManager::finished, &eLoop, &QEventLoop::quit);
timeOutTimer.setSingleShot(true);
timeOutTimer.setInterval(timeOut.count());
timeOutTimer.start();
auto resetTimeOut = [&timeOutTimer]() timeOutTimer.start(); ;
QNetworkReply* reply = action(nam);
QObject::connect(reply, &QNetworkReply::uploadProgress, resetTimeOut);
QObject::connect(reply, &QNetworkReply::downloadProgress, resetTimeOut);
eLoop.exec();
if (!timeOutTimer.isActive())
throw std::runtime_error("Time out"); // Probably custom exception
const int httpStatus
= reply->attribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute).toInt();
auto content = TakeContent(*reply); // reply->readAll and decompression
return RequestResulthttpStatus, content;
然后是get/delete/post/..的函数,类似于
auto RequestGet(const QNetworkRequest& request)
return ExecuteRequest([&](QNetworkAccessManager& nam) return nam.get(request); ,
timeOut);
auto RequestDelete(const QNetworkRequest& request)
return ExecuteRequest([&](QNetworkAccessManager& nam)
return nam.deleteResource(request);
,
timeOut);
auto RequestPost(const QNetworkRequest& request, QHttpMultiPart& multiPart)
return ExecuteRequest([&](QNetworkAccessManager& nam)
return nam.post(request, &multiPart);
,
timeOut);
然后,对于您的代码,我会做类似的事情
Mainwindow::login()
const auto getRes = RequestGet(..);
// ...
const auto postRes = RequestPost(..);
// ...
如果你不想阻塞调用,你可以使用 thread 和 future。
【讨论】:
以上是关于使用 QNetworkManager 在 QT 中设计多个嵌套的 GET/POST 的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
QTJambi - 来自线程的 QNetworkManager 不发出信号
QWebkit QWebSettings 缓存和 QNetworkManager QNetworkDiskCache 有啥区别?