[Interest] QNetworkReply lambdas?

Jérôme Godbout godboutj at amotus.ca
Wed Jun 2 17:16:46 CEST 2021

Hi, might help, this won’t answer you question directly but might give some helper idea to ease the pain. What we did is a wrapper around QNetworkAccessManager class call RequestManager that own a QNetworkManager. It expose the following methods:

QNetworkReply* postRequest(QNetworkRequest& request, const QByteArray& payload);
// Do the same for put, update, get…

And signal slots:
    void replySuccess(QNetworkReply* reply);
    void replyError(QNetworkReply* reply);

public slots:
    void handleFinished(QNetworkReply *networkReply);

It manage the return code immediate and signal then valide the answer is a success or a failure. You can store the context or object into a map with your request, the reply will have the request into it so you can load back the needed information when you receive the replySuccess or reply Error signals back.  Make some helper to convert you payload to QByteArray so you can use it with json, text, etc…

I also made some ScopeAction class so my NetworkAccess manager reply handler can make sure the delete later is not forgetten:

connect(&network_manager, &QNetworkAccessManager::finished, this, &RequestManager::handleFinished);

void RequestManager::handleFinished(QNetworkReply *networkReply)
    ScopeAction action_delete([&](){ networkReply->deleteLater(); });
… // process the reply error or success here and emit either the replySuccess or replyError signal here, this need to be non queued connection to avoid bad object access.

This helped me a lot to clean my network management for upper layer. So I can simply connect to the reply success or replyError and with the request pointer form the reply you can load the associated data and continue form that point easily.

The async/await would be nice, but I’m not sure this would play well with the Qt event loop and the object memory management. They are also super hard to debug the call stack is lost.

Jérôme Godbout, B. Ing.

Software / Firmware Team Lead
O: (418) 682-3636 ext.: 114
C: (581) 777-0050
godboutj at dimonoff.com<mailto:godboutj at dimonoff.com>
1015 Avenue Wilfrid-Pelletier,
Québec, QC G1W 0C4, 4e étage

From: Interest <interest-bounces at qt-project.org> on behalf of Jason H <jhihn at gmx.com>
Date: Wednesday, June 2, 2021 at 10:41 AM
To: interestqt-project.org <interest at qt-project.org>
Subject: [Interest] QNetworkReply lambdas?
I'm trying to figure out a more flexible way to do QNetworkReply. Ideally this would be through some async/await but I don't think Qt is "there" yet. (C++20 defines async/await, but there is not a library yet, and even Qt6 doesn't target C++20). So the callback lambda handler looks like the best option for now.

I have a QObject derived class, with a post() function. It takes an endpoint, and object (to be converted to JSON) and a lambda. Example:
remoteCloud->post("/login", credentials, [=](QNetworkReply* reply){
        if (reply->error() == QNetworkReply::NoError) {
                           {{"synced", QDateTime::currentDateTime()}},
                           {{"cartridgeId", map["cartridgeId"]}});

With an implementation of:
template<typename F>
QNetworkReply *RemoteCloud::post(const QString& endpoint, const QVariantMap& item, F &lambda) {
        QNetworkReply* reply = m_nam.post(QNetworkRequest(endpoint), JSON(item));
        connect(reply, &QNetworkReply::finished, lambda);
        return reply;

Note that a lot of the Qt examples use a connect statement like this:
connect(reply, &QNetworkReply::finished, [request, reply](){ ... });

But when I tried to set this up, I either got static assert errors or l-value errors.

However I am trying to go one better and have my RemoteCloud::post set up the connect with the lambda. Is this possible?

Interest mailing list
Interest at qt-project.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20210602/85a98188/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image001.png
Type: image/png
Size: 13927 bytes
Desc: image001.png
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20210602/85a98188/attachment.png>

More information about the Interest mailing list