Qt World Summit: Register Today!

Non-blocking QML

  • Situation
    You either have a QObject derivative that exposes a Q_INVOKABLE method to QML, say myapi.myfunc.. or you have a pure JavaScript function myjsfunc defined in the QML code. In both you do some heavy calculations and/or (network) I/O.

    First: both myapi.myfunc and myjsfunc are asynchronous and needs proper async handling
    Second: You don't want neither myapi.myfunc nor myjsfunc to block the event loop while it's executing

    Possible Solution
    Return a Promise object! and let the user define the handling on it. In QML/JavaScript you can then define some asynchronous logic this way:

    import "myfsfunc.js" as JsBusinessLogic
    SomeItem {
    	onSomething: {
    			function(firstResult) {
    				//success! make another async call
    				return JsBusinessLogic.myjsfunc(firstResult)
    			function(err, msg) {
    				//failure! myfunc returned an error
    			function(secondResult) {
    				//success! second call succeeded, EXIT
    			function(err, msg) {
    				//failure! second call returned an error  
    		.catch(function() {
    			//something went seriously wrong

    Meanwhile myjsfunc could look somewhat like this:

    function myjsfunc() {
    	return new Promise(function(resolve, reject) {  
    		//do some heavy lifting...
    		if(result == good) {
    		reject("baaaad results, error!")

    The promise object allows easy chaining of async operations and proper error and exception handling, but it still wont't change the fact that it's executed by the event loop and will inevitably block it, which ofcourse is unacceptable.

    So.... to make the async Promise non-blocking, I'd need to implement the Promise class in a way that uses a thread pool to execute the Promises in the background?
    This way when you call an invokable C++ method or a JS function both create and return a Promise object and exit! not blocking the loop any longer!, right?!
    The promise itself is then executed in a separate thread from the thread pool in the background. When it's finished its calculation and/or waiting for external resources it will run the JS handlers defined by then() or catch() in the event loop again, which won't block much.

    So did I correctly understand it? Would such kind of a Promise implementation work as described? Or is there probably an easier way?


    You might ask me why I'm implementing parts of the business logic in pure JavaScript when JS is not meant to be used for this in Qt? Well... you see.. executing 3rd party C++ is not an option if you want to build a safe OS basis, that's why JavaScript does the logic, JavaScript is easily sandboxed by the QQmlEngine while C++ is extraordinary hard to sandbox. Also using JavaScript for logic like this is what it was eventually designed for.. it's a scripting language and I use it to glue low-level modules and APIs together, just in an asynchronous, non-blocking way.

  • This is the kind of things you become Qt Champion for: https://github.com/benlau/quickpromise

    Big up to the way you ask questions!

  • This post is deleted!

  • After a detailed research of various asynchronous techniques such as Promises, Futures, Tasks and Reactive Extensions we came with a new paradigm that solved all our asynchronous problems very elegantly: The Streams Paradigm

    It's inspired by the reactive approach, though superior in many aspects such as abstraction, abortion, resumables etc.

    It's a completely rethought way of writing declarative code, making complex asynchronous operations and transactions (and probably even concurrency) a piece of cake! Nearly everything can be represented, thus abstracted away by a stream..

    • UI Elements
    • Sockets
    • Requests (HTTP etc.)
    • Calculations
    • the list goes on...

    This way streams become a consistent protocol of asynchronous and concurrent communication between various application components ranging from the UI frontend to the networked backend.

    We published the first beta release of a QML implementation with a working example aboard, be sure to check it out!