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

Time:09-24

so I wrote a programm for my thesis in Qt and now i am supposed to turn it into a working web assembly, which wasnt a real problem except for the filedownload part. I rewrote my filedownload method from:

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

To this:

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

and the problem is that the return doesnt wait for the lambda function because its asynch... I then tried using eventloops which works fine in the Destop applikation but isnt supported in the webassembly Applikation.

So does someone have a good idea how to wait for the fileContentReady Function?

CodePudding user response:

As far as I know, Qt for WebAssembly currently does not support waiting using event loops (at least Qt 6.2 does not). See Qt wiki:

"Nested event loops are not supported. Applications should not call e.g. QDialog::exec() or create a new QEventLoop object." https://wiki.qt.io/Qt_for_WebAssembly

So you would have to modify your method to handle the asynchronous call. What I mean is that whatever you want to do with the file, you can write directly into the fileContentReady lambda you have. If this is a generic function, you can let the caller register a done callback to execute when the file is ready. Something like:

    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`
  });

Also, about the usage of QMessageBox exec(). This can also cause problems as it internally creates a nested event loop which is not yet supported in Qt for WebAssembly. Instead use the show() method.

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