Как правильно использовать QStateMachine для запросов последовательной сети - PullRequest
0 голосов
/ 21 мая 2019

Мне нужно сделать несколько последовательных запросов в зависимости от размера текста. Я знаю о QEventLoop, но я хочу избежать использования вложенных циклов, и мне нужно иметь возможность прерывать мои сетевые запросы. Поэтому я решил использовать QStateMachine, как подсказано в этом ответе в комментариях.

Это мои ученики:

    QString m_text;
    QStateMachine *m_stateMachine;
    QNetworkAccessManager *m_networkManager;
    QPointer<QNetworkReply> m_currentReply; // Use QPointer to check if request was deleted.

В этой функции я создаю свой конечный автомат динамически (путем разделения текста для запроса по частям):

void myClass::buildStateMachine()
{
    QString unsendedText = m_text;
    auto *nextTranslationState = new QState(m_stateMachine);
    m_stateMachine->setInitialState(nextTranslationState);

    while (!unsendedText.isEmpty()) {
        auto *currentTranslationState = nextTranslationState;
        nextTranslationState = new QState(m_stateMachine);

        const int splitIndex = getSplitIndex(unsendedText);
        auto *requestingState = new QState(currentTranslationState);
        requestingState->setProperty(myTextProperty, unsendedText.left(splitIndex)); // To get this text in requestData()
        connect(requestingState, &QState::entered, this, &MyClass::requestMethod);
        currentTranslationState->setInitialState(requestingState);
        currentTranslationState->addTransition(currentTranslationState, &QState::finished, nextTranslationState);

        // Remove the parsed part from the next parsing
        unsendedText = unsendedText.mid(splitIndex);
    }

    auto *finalTranslationState = new QFinalState(m_stateMachine);
    nextTranslationState->addTransition(finalTranslationState);
}

В этой функции я делаю запросы:

void myClass::requestData()
{
    auto *requestingState = qobject_cast<QState *>(sender());
    QUrl url(...);

    m_currentReply = m_networkManager->get(QNetworkRequest(url));
    connect(m_currentReply, &QNetworkReply::finished, this, MyClass::parseData);
    connect(m_currentReply, &QNetworkReply::finished, &QNetworkReply::deleteLater);

    auto *finalState = new QFinalState(requestingState->parentState());
    requestingState->addTransition(m_currentReply, &QNetworkReply::destroyed, finalState);
}

Это хорошее решение? Это кажется многословным для меня. Особенно, если я использую вложенные состояния для вложенных сетевых запросов (а также при сбое при переходе в дочерние состояния, я не знаю, как его отладить).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...