Мне нужно сделать несколько последовательных запросов в зависимости от размера текста. Я знаю о 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);
}
Это хорошее решение? Это кажется многословным для меня. Особенно, если я использую вложенные состояния для вложенных сетевых запросов (а также при сбое при переходе в дочерние состояния, я не знаю, как его отладить).