QAxios研发笔记(一):在Qt环境下构建Promise风格的Get请求接口

背景与需求

Qt框架传统网络请求基于信号槽机制,代码逻辑分散且嵌套复杂。现代前端开发中Promise风格的异步处理更符合直觉,需在C++/Qt中实现类似axios的链式调用体验。

核心实现方案

封装QNetworkAccessManager 创建QAxios类继承QObject,内部持有QNetworkAccessManager实例。通过私有化网络管理器确保线程安全:

class QAxios : public QObject {
    Q_OBJECT
public:
    explicit QAxios(QObject *parent = nullptr);
    QAxiosPromise get(const QString &url);
private:
    QNetworkAccessManager *m_manager;
};

构建Promise对象 定义QAxiosPromise类封装异步状态,采用QSharedPointer管理生命周期:

class QAxiosPromise {
public:
    using ResolveFunc = std::function<void(QNetworkReply*)>;
    using RejectFunc = std::function<void(QNetworkReply*)>;
    
    QAxiosPromise& then(ResolveFunc resolve);
    QAxiosPromise& catchError(RejectFunc reject);
private:
    QSharedPointer<PromiseState> d;
};

实现链式调用get()方法中创建并返回Promise对象,通过lambda捕获保持上下文:

QAxiosPromise QAxios::get(const QString &url) {
    auto reply = m_manager->get(QNetworkRequest(QUrl(url)));
    return QAxiosPromise(reply);
}

Promise状态管理PromiseState内部类中处理Qt信号到Promise状态的转换:

connect(reply, &QNetworkReply::finished, [=]() {
    if(reply->error() == QNetworkReply::NoError) {
        resolve(reply);
    } else {
        reject(reply);
    }
});
关键技术点

线程安全处理 通过moveToThread将网络请求移至工作线程,主线程通过事件队列获取结果:

m_manager->moveToThread(&m_workerThread);
m_workerThread.start();

内存自动回收 利用Qt父子对象机制自动释放资源:

reply->setParent(this);

错误处理增强 支持HTTP状态码拦截和统一错误格式:

.catchError([](QNetworkReply *reply) {
    qWarning() << "HTTP" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) 
               << reply->errorString();
});
使用示例

典型链式调用场景:

QAxios axios;
axios.get("https://api.example.com/data")
    .then([](QNetworkReply *reply) {
        QByteArray data = reply->readAll();
        qDebug() << "Data received:" << data.length();
    })
    .catchError([](QNetworkReply *reply) {
        qCritical() << "Request failed:" << reply->errorString();
    });
性能优化建议
  1. 启用HTTP持久连接减少握手开销
QNetworkRequest request(url);
request.setRawHeader("Connection", "Keep-Alive");
  1. 实现请求拦截器统一添加认证头
void QAxios::addAuthHeader(const QString &token) {
    m_headers.insert("Authorization", "Bearer " + token);
}
  1. 支持响应数据缓存
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, 
                     QNetworkRequest::PreferCache);

该实现已在Qt 5.15+环境验证,完整源码见GitHub示例仓库。后续将扩展支持POST请求、拦截器系统等高级特性。

Logo

加入社区!打开量化的大门,首批课程上线啦!

更多推荐