如何在 QT Web Assembly 中返回值之前等待异步 lambda 函数完成

How to wait for Async lamda function to finish before returning value in a QT Web Assembly

所以我用 Qt 为我的论文写了一个程序,现在我应该把它变成一个工作的 Web 程序集,这不是一个真正的问题,除了文件下载部分。我重写了我的文件下载方法:

QString costumfile::read(QString filename){

    QString fileName = QFileDialog::getOpenFileName(nullptr, filename, "", "Text Files (*.txt )");
    QFile file(filename);
    qDebug()<<filename<<"filename";
    if(!file.open(QFile::ReadOnly |
                  QFile::Text))
    {
        qDebug() << " Could not open the file for reading";
        return "";
    }

    QTextStream in(&file);
    QString myText = in.readAll();

    //qDebug() << myText;


    file.close();
    return myText;
}

为此:

    QString costumfile::read(QString filename)
    
    {
        
        QMessageBox msgBox;
        QString textUser="Open" + filename;
        msgBox.setText(textUser);
        msgBox.exec();
        QString text="hallo";
        qDebug()<<filename;
    
    
        auto fileContentReady = [&](const QString &fileName, const QString &fileContent) {
    
            if (fileName.isEmpty()) {
                msgBox.setText("Error");
                msgBox.exec();
            } else {
    
                text=fileContent;
                qDebug()<<text<<"texstis";
    
                return fileContent;
            }
            return fileContent;
        };
    
        QFileDialog::getOpenFileContent(".txt",  fileContentReady);
    }

问题是 return 不等待 lambda 函数,因为它是异步的... 然后我尝试使用事件循环,它在 Destop 应用程序中运行良好,但在 webassembly 应用程序中不受支持。

那么有人知道如何等待 fileContentReady 函数吗?

据我所知,Qt for WebAssembly 目前不支持使用事件循环等待(至少 Qt 6.2 不支持)。参见 Qt 维基:

“不支持嵌套事件循环。应用程序不应调用 QDialog::exec() 或创建新的 QEventLoop 对象。” https://wiki.qt.io/Qt_for_WebAssembly

所以您将不得不修改您的方法来处理异步调用。我的意思是,无论您想对文件做什么,都可以直接写入您拥有的 fileContentReady lambda。如果这是一个通用函数,您可以让调用者注册一个 done 回调,以便在文件准备好时执行。类似于:

    QString costumfile::read(QString filename, 
                             const std::function<void(const QString&)>& done)
    {
        ...
        auto fileContentReady = [=](const QString &fileName, const QString &fileContent) {
            if (fileName.isEmpty()) {
                // Report error
            } else {
                text=fileContent;
                qDebug()<<text<<"texstis";
                done(text);
            }
        };
        QFileDialog::getOpenFileContent(".txt",  fileContentReady);
    }
  // When calling costumfile::read
  read(filename, [=] (const QString& text) {
    // Do something with `text`
  });

另外,关于QMessageBox的用法exec()。这也可能导致问题,因为它在内部创建了一个嵌套的事件循环,Qt for WebAssembly 尚不支持该循环。而是使用 show() 方法。

    auto msgBox = new QMessageBox();
    msgBox->setText(textUser);
    connect(msgBox, &QMessageBox::finished, &QMessageBox::deleteLater);
    msgBox->show();