QT中使用QNetworkReply时异步调用导致数据为空的问题
解决QNetworkReply异步请求导致parse提前执行的问题
问题根源
QNetworkAccessManager的网络请求是异步非阻塞的,调用fetchDataFromAPI()后函数会立即返回,不会等待API请求完成。你在globals文件里调用fetchDataFromAPI()后马上执行parse(),此时finished()槽函数还没触发,nioshWPDataFromAPI自然是空的。
解决方案
方案一:在请求完成后自动调用parse
直接在finished()函数的成功分支里调用parse(),确保数据准备好后再解析:
void NioshFunc::finished(){ if(reply->error()) { qDebug() << "ERROR!"; qDebug() << reply->errorString(); qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); }else{ qDebug() << "SUCCESS"; qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); nioshWPDataFromAPI = QJsonDocument::fromJson(dataBuffer); qDebug() << nioshWPDataFromAPI; dataBuffer.clear(); // 数据就绪后立即解析 bool parseResult = parse(); qDebug() << "解析结果:" << parseResult; } reply->deleteLater(); }
之后globals里只需要调用fetchDataFromAPI()即可,不需要手动调用parse()。
方案二:用信号通知外部解析完成
如果需要在globals里处理解析完成后的逻辑,可以给NioshFunc类添加一个自定义信号,在解析完成后发射:
- 先在NioshFunc类的头文件里声明信号:
class NioshFunc : public QObject { Q_OBJECT signals: void dataFetchedAndParsed(bool success); // 自定义信号 // ... 其他成员 };
- 修改
parse()函数,最后发射信号(同时修正一处笔误):
bool NioshFunc::parse(){ Globals *g = Globals::getHandle(); if (nioshWPDataFromAPI.isEmpty() || nioshWPDataFromAPI.isNull()) { emit dataFetchedAndParsed(false); return false; } QVariantMap root = nioshWPDataFromAPI.toVariant().toMap(); if (root.isEmpty()) { emit dataFetchedAndParsed(false); return false; } QVariantMap d = root["d"].toMap(); if (d.isEmpty()) { emit dataFetchedAndParsed(false); return false; } QVariantList results = d["results"].toList(); if (results.isEmpty()) { emit dataFetchedAndParsed(false); return false; } foreach (QVariant varResult, results) { QVariantMap result = varResult.toMap(); if (result.isEmpty()) { emit dataFetchedAndParsed(false); return false; } g->struct_tableColumn.input.duration = result["Duration"].toString(); g->struct_tableColumn.input.id = result["Id"].toString(); // 修正笔误:这里的id应该是全局结构体里的变量 if (g->struct_tableColumn.input.id.isEmpty() || g->struct_tableColumn.input.id.isNull()) { emit dataFetchedAndParsed(false); return false; } g->struct_tableColumn.input.load_cumul_Limit = result["LoadCumulLimit"].toString(); g->struct_tableColumn.input.Notes = result["Notes"].toString(); qDebug() << g->struct_tableColumn.input.id << g->struct_tableColumn.input.duration << g->struct_tableColumn.input.load_cumul_Limit << g->struct_tableColumn.input.Notes; } emit dataFetchedAndParsed(true); return true; }
- 在globals里连接信号,处理后续逻辑:
// 假设nioshFunc是NioshFunc的实例 connect(nioshFunc, &NioshFunc::dataFetchedAndParsed, this, [=](bool success){ if(success){ // 解析成功后的操作 qDebug() << "数据解析完成,可以进行后续处理"; }else{ qDebug() << "数据解析失败"; } }); // 只需要触发请求即可 nioshFunc->fetchDataFromAPI();
额外提示
你parse()函数里原本的if (id.isEmpty() || id.isNull())存在未定义变量的问题,已经在方案二中修正为g->struct_tableColumn.input.id,避免编译报错。
内容的提问来源于stack exchange,提问作者Gia Huy
相关产品推荐
相关产品推荐

