QIviPendingReply 类

template <typename T> class QIviPendingReply

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

头文件 #include <QIviPendingReply>
qmakeQT += ivicore
实例化 PendingReply
继承 QIviPendingReplyBase

公共函数

QIviPendingReply(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()>())

静态公共成员

QIviPendingReply<T>createFailedReply()

详细描述

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

QFuture 相比,QIviPendingReply 也可以在 QML 中工作,并且特别为此目的而制作。存储在 QIviPendingReply 中的数据在所有副本之间隐式共享。这有助于降低内存和性能开销。

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

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

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

编写返回 QIviPendingReply 的函数

编写返回 QIviPendingReply 的函数时,通常需要在实际操作之前执行一些输入验证并返回。不使用 QIviPendingReply,可以编写函数如下:

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变为同步。

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

将上述函数完全异步重写为使用QIviPendingReply,如下所示:

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

    QIviPendingReply<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;
}

现在立即创建一个新的QIviPendingReply并将其传递到连接声明中使用的lambda函数。实际的任务稍后开始,并且返回响应对象。一旦异步API发出displayNameChanged信号,lambda函数就会被执行,QIviPendingReply被标记为成功,并将值设置到displayName()。

注意:所有QIviPendingReply的副本都使用隐式共享。一旦所有待处理回复的副本被删除,该数据就会被释放。

使用返回QIviPendingReply的函数

当使用返回QIviPendingReply的函数时,首先要检查是否已经可用结果,使用isResultAvailable属性,并相应行动。之后,您可以对QIviPendingReplyWatcher提供的信号进行连接。

信号和槽

为了保持内存足迹低,QIviPendingReply不直接提供信号,因为它不需要从QObject派生,而是使用Q_GADGET宏。要在一旦有结果准备好的时候被告知,可以使用QIviPendingReplyWatcher。可以使用监视器属性检索监视器。

以下是一个使用上述API的示例:

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

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

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

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

成员函数文档

QIviPendingReply::QIviPendingReply(const T &value)

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

这等价于

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

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

创建一个标记为失败的回复对象。这在函数返回回复的错误情况下很有用。

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

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

T QIviPendingReply::reply() const

返回回复的结果。如果没有设置结果或者回复被标记为失败,将返回默认构造的值。

另请参阅:setSuccesssetFailed

void QIviPendingReply::setSuccess(const T &val)

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

注意:结果只能设置一次,之后无法再次更改。

另请参阅:setFailed.

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

设置结果传递时一次调用的C++回调函数。如果回复成功,则调用success;否则,调用failed

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

如果在此函数被调用时,待处理回复的结果已经可用,则立即运行相应的回调函数。

另请参阅:QIviPendingReplyBase::then.

相关非成员

template <typename T> void qIviRegisterPendingReplyType(const char *name = nullptr)

注册类型名称name以在QIviPendingReply内部使用类型T。任何具有公共默认构造函数、公共拷贝构造函数和公共析构函数的类或结构都可以注册。

此函数要求T是调用该函数时的完全定义的类型。对于指针类型,它还要求指针指向的类型是完全定义的。使用Q_DECLARE_OPAQUE_POINTER()可以注册指向已经声明的类型的指针。

有关更多信息,请参阅qRegisterMetaType.

void qiviRegisterPendingReplyBasicTypes()

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

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

©2020 The Qt Company Ltd. 本文档中的文档贡献是各自所有者的版权。本文档是根据自由软件基金会发布的GNU自由文档许可证版本1.3的条款提供的。Qt及其相关标志是芬兰或全球其他国家的The Qt Company Ltd.的商标。所有其他商标均为其各自所有者的财产。