[Development] [QtQuick] Is Qt.import() really async? How to cope with it?

Ronan Jouchet ronan.jouchet at cadensimaging.com
Mon Nov 9 16:14:10 CET 2015


(This is a mailing list re-post of the forum.qt.io thread at [forum1])

Hi.

I want a QML component to call a js domain/business-specific library, 
itself calling a generic library. Exactly the use case depicted by the 
"Including a JavaScript Resource from Another JavaScript Resource" 
[doc1] documentation entry: ui.qml → script.js → factorial.js.

In this example, script.js calls `Qt.include("factorial.js")`, then 
immediately calls the `factorial(value)` function included from 
factorial.js.

But trying exactly this in my project, instead of working as expected, I 
end up with error `script.js:6: ReferenceError: factorial is not 
defined` :-/ . Why? Because `Qt.include()` is asynchronous! As mentioned 
by Qt.include()'s documentation [doc2],

"Qt.include() returns an object that describes the status of the 
operation [...]. The status property will be updated as the operation 
progresses. If provided, callback is invoked when the operation 
completes. The callback is passed the same object as is returned from 
the `Qt.include()` call."

And indeed, true to the method documentation, if trying a synchronous 
approach, the Qt.include() call yields the following object:

     {
       "OK":0,
       "LOADING":1,
       "NETWORK_ERROR":2,
       "EXCEPTION":3,
       "status":1
     }

`status` equals "LOADING", our child method hasn't been copied to caller 
scope yet. Okay. So instead of going synchronous, let's play ball and 
make the example async with a callback:

     // script.js
     function showCalculations(value) {
       console.log("Just a top-level scope stub, to be replaced on 
import of factorial.js");
     }

     Qt.include("factorial.js", function(includeStatus) {
       console.log(includeStatus); // logs 0 now, great
       showCalculations = function(value) {
           console.log(
               "Call factorial() from script.js:",
               factorial(value));
       }
     });

The good news here is that the `includeStatus.status` being logged is 
now 0, the callback did fire on successful import as promised.

But the bad news is of course that, because the include is asynchronous 
and non-blocking, it will not not be resolved at the time QML needs it, 
and QML will use the shim, logging "Just a top-level scope stub...". Of 
course, not including a stub will result in worse: the function not 
being found.

→ Am I missing anything / is the documentation effectively incorrect? Or 
am I facing a special case? My qml and scripts are part of a qrc, could 
it be interfering?

Thanks for your help.

[forum1] 
https://forum.qt.io/topic/60424/how-to-cope-with-the-asynchronous-ness-of-qt-import
[doc1] 
http://doc.qt.io/qt-5/qtqml-javascript-imports.html#including-a-javascript-resource-from-another-javascript-resource
[doc2] http://doc.qt.io/qt-5/qml-qtqml-qt.html#include-method

-- 
Ronan



More information about the Development mailing list