QIfPendingReply 类

template <typename T> class QIfPendingReply

提供异步结果的模板类。 更多...

头文件 #include <QIfPendingReply>
qmakeQT += interfaceframework
实例化自 PendingReply
继承自 QIfPendingReplyBase

公共函数

QIfPendingReply(const T &value)
Treply() const
voidsetSuccess(const T &val)
voidthen(const std::function<void (const T &)> &success, const std::function<void ()> &failed = std::function<void()>())

静态公共成员

QIfPendingReply<T>createFailedReply()
typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, void>::typeqIfRegisterPendingReplyType(const char *name = nullptr)
voidqifRegisterPendingReplyBasicTypes()

详细描述

QIfPendingReply 是一个提供异步结果的模板类。它可以作为异步函数的返回值,类似于 QFuture

QFuture 不同,QIfPendingReply also works in QML,并且特别为此设计。存储在 QIfPendingReply 中的数据在所有回复对象的副本之间隐式共享,这有助于保持内存和性能的低占用。

QML API 非常类似于 JavaScript Promises,同时 C++ API 提供了对 Qt 的信号和槽的支持。

QIfPendingReply 提持特定类型的结果。类型需要有默认构造函数和复制构造函数。默认情况下,支持大多数最基本 Qt 类型。可以通过使用 qIfRegisterPendingReplyType 函数添加新类型。

创建 QIfPendingReply 时,它还没有设置有效的结果。这可以通过 resultAvailable 属性来检查。可以使用 setFailed 或 setSuccess 函数设置回复的结果。使用此函数设置结果只能进行一次,并且以后不能更改。可以通过 success 属性确定 QIfPendingReply 是否成功。

编写返回 QIfPendingReply 的函数

在编写返回QIfPendingReply的函数时,通常需要在实际操作之前进行一些输入验证并返回。如果不使用QIfPendingReply,则函数可能会写得更像这样

QString displayName(const QUuid &id)
{
    if (id.isNull)
        return QString();

    //do something and wait until the result is ready (synchronous)
    asyncAPI.getDisplayName(id);
    asyncAPI.waitForFinished(&displayNameChanged);
    return asyncAPI.displayName();
}

此函数使用异步API,例如由IPC提供的API。getDisplayName(id)开始任务,一旦结果准备就绪,则会发出displayNameChanged信号,实际的值可以通过displayName()函数读取。提供的函数使用waitForFinished()方法实际等待信号的发出,返回值并使此API同步。

将此代码移至使用QIfPendingReply时,验证检查需要修复以返回有效的QIfPendingReply。为了更方便地返回失败的回复,可以使用QIfPendingReply::createFailedReply()函数。

完全异步重写上述函数使用QIfPendingReply将类似于以下内容

QIfPendingReply<QString> displayName(const QUuid &id)
{
    if (id.isNull)
        return QIfPendingReply<QString>::createFailedReply();

    QIfPendingReply<QString> reply
    //connect to the change signal and set the result to the async reply when ready
    connect(asyncAPI, &displayNameChanged, this, [reply, asyncAPI]() mutable {
            reply.setSuccess(asyncAPI.displayName());
    });
    //start getting the name
    asyncAPI.getDisplayName(id);
    return reply;
}

现在立即创建一个新的QIfPendingReply并传递给connect语句中使用的lambda。实际任务随后启动,并返回回复对象。一旦异步API发出displayNameChanged信号,lambda将被执行,QIfPendingReply将被标记为成功,并将其值设置为displayName()。

注意:所有QIfPendingReply的副本都使用隐式共享。当所有待处理的回复副本被删除时,此数据将释放。

使用返回QIfPendingReply的函数

在使用返回QIfPendingReply的函数时,首先应检查是否已可用结果使用isResultAvailable属性,并按相应执行。之后,您可以开始连接由QIfPendingReplyWatcher提供的信号。

信号和槽

为了保持内存占用低,QIfPendingReply不直接提供信号,因为它不需要从QObject继承,而使用Q_GADGET宏。要在一旦结果准备就绪时通知,可以使用QIfPendingReplyWatcher。可以使用watcher属性检索监视器。

以下是一个关于如何使用上述API的示例

QUuid uuid = createUuid();
QIfPendingReply<QString> reply = displayName(uuid);
if (reply.isResultAvailable()) {
    if (reply.isSuccessfull())
        useDisplayName(reply.value());
    else
        qWarning("getting the displayName failed");
} else {
    connect(reply.watcher(), &QIfPendingReplyWatcher::valueChanged, this, [this, reply]() {
        if (reply.isSuccessfull())
            useDisplayName(reply.value());
        else
            qWarning("getting the displayName failed");
    });
}

如上所述,首先检查待处理的回复是否已有结果,如果没有,则使用监视器的信号来响应valueChanged信号。

注意:返回的QIfPendingReplyWatcher属于QIfPendingReply及其所有副本。如果所有QIfPendingReply的副本都被删除,则其QIfPendingReplyWatcher也会被删除。

有关在QML中的使用,请参阅QML文档。

成员函数文档

QIfPendingReply::QIfPendingReply(const T &value)

创建一个新的QIfPendingReply,用于存储类型T。使用value将待处理的回复设置为成功。

此操作等同于

QIfPendingReply<T> reply.
reply.setSuccess(value);

[静态] QIfPendingReply<T> QIfPendingReply::createFailedReply()

创建一个标记为失败的回复对象。在函数返回回复的错误情况中,这是一个方便的操作。

QIfPendingReply<QString> doSomething(int value)
{
    if (value <= 0) {
        qWarning("The value needs to be bigger than 0");
        return QIfPendingReply<QString>::createFailedReply()
    }

    QIfPendingReply<QString> reply;
    ...
    return reply;
}

T QIfPendingReply::reply() const

返回回复的结果。如果没有设置结果或当回复标记为失败时,返回一个默认构造的值。

另请参阅 setSuccesssetFailed.

void QIfPendingReply::setSuccess(const T &val)

将回复的结果设置为 val 并将该回复标记为成功。

注意: 结果只能设置一次,并且以后无法更改。

另请参阅 setFailed.

void QIfPendingReply::then(const std::function<void (const T &)> &success, const std::function<void ()> &failed = std::function<void()>())

设置在结果交付时调用的 C++ 回调。如果回复成功 success 被调用;否则 failed 被调用。

success 回调接收回复值作为参数。

如果在调用此函数时挂起的回复结果已经可用,则相应的回调函数将立即运行。

另请参阅 QIfPendingReplyBase::then.

相关非成员

template <typename T> typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, void>::type qIfRegisterPendingReplyType(const char *name = nullptr)

将类型名 name 记录在用于 QIfPendingReply 的类型 T。任何具有公共默认构造函数、公共拷贝构造函数和公共析构函数的类或结构体都可以注册。

此函数要求在函数调用时 T 是一个完全定义的类型。对于指针类型,还要求指向的类型是完全定义的。使用 Q_DECLARE_OPAQUE_POINTER() 能够注册前向声明的类型的指针。

请参阅 qRegisterMetaType 获取更多信息。

void qifRegisterPendingReplyBasicTypes()

将所有 Qt 基本类型的 QIfPendingReply 注册到元类型系统中。

通常在创建 QCoreApplicationQIfPendingReply 时自动调用此函数,无需手动调用。

© 2024 Qt 公司有限公司。此处包含的文档贡献是各自拥有者的版权。此处提供的文档根据自由软件基金会发布的 GNU自由文档许可协议版本1.3 的条款许可。Qt 及其LOGO是芬兰及/或其他国家的 The Qt Company Ltd. 的商标。所有其他商标均为各自拥有者的财产。