Qt多线程异步post请求,递归POST

背景:后台需要静默调用接口访问数据,不能影响UI线程操作,数据可能会有上万,一次不能全传过来,递归自己调用接口。服务器会在接口返回值中totaEelements返回当前筛选条件下的总条数,比如pageNumber为1,pageSize为100,意味着获取全部数据,如共329条,按照每页100分开,现在获取第1页。totaEelements为329。

struct NetworkReply
{
	QNetworkReply::NetworkError error = QNetworkReply::NetworkError::NoError;
	QByteArray content;
	QString errorString = "";
};
class NetworkHelper :public QObject
{
	Q_OBJECT
public:

	static NetworkReply post(const QString url, const QByteArray content, int timeout = NetworkSet::getInstance()->getDelayTime());
	/**
	 * \brief 同步post请求
	 * \param url 地址如"/api/pack/list"
	 * \param content json内容
	 * \param timeout 超时设置(毫秒)
	 * \return NetworkReply请求结果
	 */
	static NetworkReply postJson(const QString url, const QByteArray content, int timeout = NetworkSet::getInstance()->getDelayTime());
	/**
	 * \brief 异步post请求
	 * \param manager 请求管理对象,在函数调用处绑定信号和自定义的槽connect(manager, &QNetworkAccessManager::finished,***,***);
	 * \param url  地址如"/api/pack/list"
	 * \param content json内容
	 */
	static void postJson(QNetworkAccessManager* manager, const QString url, const QByteArray content);



	/**
	 * \brief 获取登记人员列表 [异步]
	 * \param pageNumber 页码
	 * \param pageSize 每页数量
	 * \param startTime 操作开始时间yyyy-MM-dd HH:mm:ss
	 * \param endTime 操作结束时间yyyy-MM-dd HH:mm:ss
	 */
	static void getUserListSync(int pageNumber, int pageSize, QString startTime = "", QString endTime = "");
	
};

```cpp


NetworkReply NetworkHelper::post(const QString url, const QByteArray content, int timeout)
{
	QEventLoop eventloop;
	QTimer timer;
	timer.singleShot(timeout, &eventloop, &QEventLoop::quit);

	QNetworkAccessManager manager;
	manager.setNetworkAccessible(QNetworkAccessManager::Accessible);
	manager.setProxy(QNetworkProxy::NoProxy);
	QNetworkRequest request;
	request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");//二进制流类型
	request.setUrl(QUrl(NetworkSet::getInstance()->getUrl().toString() + url));
	timer.start(timeout);

	QNetworkReply* reply = manager.post(request, content);
	connect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
	eventloop.exec(QEventLoop::ExcludeUserInputEvents); //开启事件循环
	NetworkReply result;
	if (!timer.isActive())
	{
		//超时,未知状态
		disconnect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
		reply->abort();
		reply->deleteLater();
		result.error = QNetworkReply::NetworkError::TimeoutError;
		return result;
	}
	reply->abort();
	reply->deleteLater();
	result.error = reply->error();
	result.errorString = reply->errorString();
	result.content = reply->readAll();
	return result;
}

NetworkReply NetworkHelper::postJson(const QString url, const QByteArray content, int timeout)
{
	QEventLoop eventloop;
	QTimer timer;
	timer.singleShot(timeout, &eventloop, &QEventLoop::quit);

	QNetworkAccessManager manager;
	manager.setNetworkAccessible(QNetworkAccessManager::Accessible);
	manager.setProxy(QNetworkProxy::NoProxy);
	QNetworkRequest request;
	request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");
	request.setUrl(QUrl(NetworkSet::getInstance()->getUrl().toString() + url));
	timer.start(timeout);
	QNetworkReply* reply = manager.post(request, content);
	connect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
	eventloop.exec(QEventLoop::ExcludeUserInputEvents); //开启事件循环
	NetworkReply result;
	if (!timer.isActive())
	{
		//超时,未知状态
		disconnect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
		reply->abort();
		reply->deleteLater();
		result.error = QNetworkReply::NetworkError::TimeoutError;
		return result;
	}
	reply->abort();
	reply->deleteLater();
	result.error = reply->error();
	result.errorString = reply->errorString();
	result.content = reply->readAll();
	return result;
}

void NetworkHelper::postJson(QNetworkAccessManager* manager, const QString url, const QByteArray content)
{
	manager->setNetworkAccessible(QNetworkAccessManager::Accessible);
	manager->setProxy(QNetworkProxy::NoProxy);
	QNetworkRequest request;
	request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");
	request.setUrl(QUrl(NetworkSet::getInstance()->getUrl().toString() + url));
	manager->post(request, content);
}

void NetworkHelper::getUserListSync(int pageNumber, int pageSize, QString startTime, QString endTime)
{
	if (NetworkSet::getInstance()->getToken().isEmpty())
		return;
	LocalLog->info(QString(u8"准备获取用户列表第%1页%2个").arg(pageNumber).arg(pageSize));
	//body 参数
	QJsonObject json;
	QJsonObject jsonData;
	QJsonObject data;
	data.insert("pageNumber", pageNumber);
	data.insert("pageSize", pageSize);
	jsonData.insert("tokenId", NetworkSet::getInstance()->getToken());
	jsonData.insert("data", data);
	json.insert("jsonData", jsonData);
	QJsonDocument document;
	document.setObject(json);

	QByteArray dataArray = document.toJson(QJsonDocument::Compact);

	QString apiPath = "/api/userlist";
	NetworkReply replay = NetworkHelper::postJson(apiPath, dataArray);

	if (replay.error == QNetworkReply::NetworkError::TimeoutError)
	{
		LocalLog->debug(apiPath + u8"请求超时");
	}
	else
	{
		if (replay.error != QNetworkReply::NetworkError::NoError)
		{
			LocalLog->debug(apiPath + u8"请求出错 : " + replay.errorString);
		}
		else
		{
			QJsonDocument document = QJsonDocument::fromJson(replay.content, new QJsonParseError);
			QJsonObject rootObj = document.object();
			QString code = rootObj["code"].toString(); //服务器返回的状态码
			bool success = rootObj["success"].toBool(); //是否成功
			QString message = rootObj["message"].toString();
			if (code == "200" && success)
			{
				if (rootObj.contains("data"))
				{
					QJsonObject subObj = rootObj.value("data").toObject();
					QString token = subObj["tokenId"].toString();
					int totaEelements = subObj["totaEelements"].toString().toInt();
					if (subObj.contains("items"))
					{
						QList<User>users;
						QJsonArray itemsObj = subObj.value("items").toArray();
						for (int i = 0; i < itemsObj.count(); ++i)
						{
							QJsonObject item = itemsObj.at(i).toObject();
							User user;
							user.userName = item["userName"].toString(); //用户名
							user.emplName = item["emplName"].toString(); //姓名
							users.push_back(user);
						}
						DataBaseOperation::addUsers(users);
					}
					if (pageNumber * pageSize < totaEelements)
					{
						LocalLog->info(u8"发现数据不足,自动调用");
						getUserListSync(pageNumber + 1, pageSize, startTime, endTime);
					}
				}
			}
			else
				LocalLog->error(apiPath + message);
		}
	}
}

调用的话只需要利用QtConcurrent::run临时开启一个子线程即可,从第一页开始获取,每次最多获取5000个,如果总数据太多,每次获取太多条等待时间太长,容易产生一些额外情况

QtConcurrent::run([=]
			{
				NetworkHelper::getUserListSync(1, 5000);
			});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值