【发布时间】:2015-05-11 16:34:55
【问题描述】:
我想创建一个通过 REST API 访问数据的类,例如:
class MeteoStation{
int getLatestTemperature();
int getLatestPessure();
private:
QNetworkManager nmng;
}
我该如何实现这些方法?通常我使用类似的东西:
int MeteoStation::getLatestTemperature(){
...
QEventLoop eventLoop;
connect(&m_nam,SIGNAL(finished(QNetworkReply*)),&eventLoop,SLOT(quit()));
QNetworkReply *reply = m_nam.get( req );
eventLoop.exec();
reply->readAll()
...
}
但是由于不推荐使用内部QEventLoop,我应该如何查看响应属于谁?
MeteoStation::MeteoStation(){
connect(&nmam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseNetworkResponse(QNetworkReply*)));
}
void MeteoStation::parseNetworkResponse( QNetworkReply *finished )
{
QByteArray data = finished->readAll();
...
是的,保存类线程会很好。你是如何在你的代码中解决这个问题的?
使调用与以下内容同步有多糟糕:
QNetworkRequest req(url);
QScopedPointer<QNetworkReply> reply(nam.get(req));
QTime timeout= QTime::currentTime().addSecs(10);
while( QTime::currentTime() < timeout && !reply->isFinished()){
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Failure" <<reply->errorString();
}
QByteArray data = reply->readAll();
【问题讨论】:
-
"我应该如何查看回复属于谁?" - 将指向创建的 QNetworkReply 对象的指针返回给 getLatestTemperature 的调用者。然后调用者可以连接到它的finished() 信号。如果你想封装错误处理或回复解析,你可以将它包装到另一个命令模式样式类中。
-
连接到 QNetworkReply 对象是个好主意。它正在解决问题:“我应该如何查看响应属于谁?”现在在等待响应?想象一下,
int MeteoStation::getLatestTemperature()最初是从某个内存映射寄存器中读取温度值,现在应该从 REST 中获取值。我可以以某种方式修改 MeteoStation 类(在库中)还是必须重新设计应用程序? -
我认为在同步 API 后面隐藏异步行为是徒劳且容易出错的:1)使用本地事件循环是许多弊端的根源,应该避免 2)你可能不想在等待网络响应进入时阻止调用者(例如在 UI 线程中)。我认为您应该重新设计应用程序以假设异步通信。从长远来看,它将防止许多严重的头痛。
-
嗯,我已经在 Qt PostgreSQL 和 C++ CouchDB 驱动程序中挖掘出来,它们都阻塞了查询结果的调用者。循环中的 Postgresql 和 curl 的 Pillowtalk。同步调用可能是邪恶的,但它们在 Qt 代码中也被广泛使用。重新设计整个应用程序是不可能的。例如,我不能简单地将类 init() 方法分解为 startInit()、continueInitWithTemperature()、continueInitWithPressure() 以及每次我询问 REST 服务器时。
标签: c++ qt rest network-programming