Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-49373

[QtQuick] Is Qt.include() really async? If yes, documentation needs fixing.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Cannot Reproduce
    • P2: Important
    • None
    • 5.5.1
    • Documentation
    • None

    Description

      Hi.

      (This is a follow-up to a forum post and a mailing-list post)

      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.
      • Finally, as suggested in the forum post, there's always the option of calling Qt.import() inside each function needing a remote function, but
        • It adds callback nested-ness and noise...
        • ... and it does so in each function requiring a Qt.include d 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.

      → 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?

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            docteam Qt Documentation Team
            ronjouch Ronan Jouchet
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes