QtWebEngine - synchronously execute JavaScript to read function result

Viewed 7279

I have the following method in one of my C++ classes (using QtWebEngine):

    QString get()
    {
        QString result;

        view->page()->runJavaScript("test();", [this](const QVariant &v)
            {
                result = v.toString();
            });

        return result;
    }

It is to execute test() JS function and return the result of this invocation.

Unfortunately, the callback is asynchronous and the program crashes. How can I make it work?

3 Answers

Dmitry's solution only works partially, unfortunately. In his example the code is invoked upon pressing a button. However, if the same code is moved to execute while the window is loading, the slot for the finished script (onScriptEnded) is never called. To fix this, I had to wrap the call to the evaluation of JS itself (called evaluateJavaScript in my project) in another QTimer::singleShot:

QTimer::singleShot(0, this, [&] { evaluateJavaScript(); });

Unfortunately, in my real project I have many calls, often one evaluation waiting for another before it to finish. It's practically impossible to use this every single time so I still look for a solution.

In the kchmviewer project, I found a very easy way to wait for the result of the runJavaScript function. The following code is part of the ViewWindow class which inherits from QWebEngineView.

int ViewWindow::getScrollbarPosition()
{
    QAtomicInt value = -1;

    page()->runJavaScript("document.body.scrollTop", [&value](const QVariant &v)
        {
            qDebug( "value retrieved: %d\n", v.toInt());
            value = v.toInt();
        });

    while (value == -1)
    {
        QApplication::processEvents();
    }

    qDebug( "scroll value %d", value.load() );
    return value;
}
Related