Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to cope with the asynchronous-ness of Qt.import() ?
QtWS25 Last Chance

How to cope with the asynchronous-ness of Qt.import() ?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
importscopejavascriptqmlasynchronous
4 Posts 2 Posters 2.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    ronjouch
    wrote on 6 Nov 2015, 18:28 last edited by ronjouch 11 Dec 2015, 15:35
    #1

    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 documentation entry: ui.qml → script.js → factorial.js.

    In the example, script.js calls Qt.include("factorial.js"), then immediately calls the factorial(value) method 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,

    "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:

    // 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? What could differ in my case? My qml and scripts are part of a qrc, could it be interfering?

    EDIT: posted too on the qt-development mailing list.

    EDIT2: created QTBUG-49373 - [QtQuick] Is Qt.include() really async? If yes, documentation needs fixing.

    1 Reply Last reply
    0
    • U Offline
      U Offline
      unai_i
      wrote on 9 Nov 2015, 21:59 last edited by
      #2

      Hi,
      If I understand correctly what you want to achieve you can do it in two different ways:

      • function showCalculations(value) {
            Qt.include("factorial.js", function(includeStatus) {
                console.log(includeStatus); // logs 0 now, great
                console.log("Call factorial() from script.js: "+factorial(value));
            }
        }
        // call  from QML:
        showCalculations(someValue);
        
      •    function showCalculations(value, callback) {
                Qt.include("factorial.js", function(includeStatus) {
                    console.log(includeStatus); // logs 0 now, great
                     callback(factorial(value));
                }
            }
        // call from QML
        showCalculations(value, function(result){
            // do something useful with result
        });
        

      Best regards.

      R 1 Reply Last reply 10 Nov 2015, 15:56
      0
      • U unai_i
        9 Nov 2015, 21:59

        Hi,
        If I understand correctly what you want to achieve you can do it in two different ways:

        • function showCalculations(value) {
              Qt.include("factorial.js", function(includeStatus) {
                  console.log(includeStatus); // logs 0 now, great
                  console.log("Call factorial() from script.js: "+factorial(value));
              }
          }
          // call  from QML:
          showCalculations(someValue);
          
        •    function showCalculations(value, callback) {
                  Qt.include("factorial.js", function(includeStatus) {
                      console.log(includeStatus); // logs 0 now, great
                       callback(factorial(value));
                  }
              }
          // call from QML
          showCalculations(value, function(result){
              // do something useful with result
          });
          

        Best regards.

        R Offline
        R Offline
        ronjouch
        wrote on 10 Nov 2015, 15:56 last edited by ronjouch 11 Nov 2015, 14:19
        #3

        @unai_i sure, thanks for bringing this. But compared to a regular import statement,

        • It adds callback nested-ness and noise...
        • ... and it does so in each function requiring a Qt.included symbol, bringing even more noise and repetition :-/ (and maybe slowing things down?), contrarily to basically all language's import statement, which makes foreign symbols available in the whole current file.

        I'm mourning a simple synchronous CommonJS-style var mylib = require('mylib'). Thanks for confirming the documentation lies.

        1 Reply Last reply
        0
        • R Offline
          R Offline
          ronjouch
          wrote on 17 Nov 2015, 22:04 last edited by
          #4

          Good news! My use case is actually well covered by simply using a regular .import "thing.js" as Thing. I don't need the specific namespace-less behavior of Qt.include; I just happened to miss .import when reading the doc, thus failing to understand that Qt.include is only a second import mechanism to be used instead of .import under very specific (documented) circumstances.

          → Doc might still deserve clarification of the async behavior, but my initial problem is gone with using .import. I updated the QTBUG

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved