From JavaScript async operations to C++/Qt



  • I've been coding in JavaScript using the new async/await operations along with Promises and I wanted to create the same thing I did using C++/Qt. That is my code in JavaScript:

    const request = require('async-request')
    
    class Biz {}
    
    class Foo extends Biz {
      async call() {
        let response = await request('https://httpbin.org/uuid')
        return JSON.parse(response['body'])
      }
    }
    
    class Bar extends Biz {
      async call() {
        let response = await request('https://httpbin.org/uuid')
        return JSON.parse(response['body'])
      }
    }
    
    class Container {
      constructor() {
        this.storage = []
      }
    
      register(obj) {
        this.storage.push(obj)
      }
    
      call() {
        Promise.all(this.storage.map(obj => obj.call()))
        .then(result => console.log([].concat(...result)));
      }
    }
    
    const container = new Container
    container.register(new Foo)
    container.register(new Bar)
    container.call()
    

    You don't have to understand everything but I'm going to show you the parts that is most important here.

    I have a container that will store instances of a type in this case is Biz.
    The container is responsible to call the call method from the registered instances asynchronously.

    Looking at the call method from the classes Foo and Bar you will notice an async keyword that means that we can use the keyword await inside of that method. In this case I used await connect(...) .

    The await operator is used to wait for a Promise. It can only be used inside an async function.
    Returns the fulfilled value of the promise, or the value itself if it's not a Promise.

    In this case I have the value of the promise that is the return of the request, I got the body as a Json and returned.

    Promise.all(this.storage.map(obj => obj.call()))
    .then(result => console.log([].concat(...result)));
    

    In JavaScript we have the Promise.all:

    The Promise.all() method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects.

    So as parameter I passed a this.storage.map:

    The map() method creates a new array with the results of calling a provided function on every element in the calling array.

    Basically map will give me each value of the array so I can handle it and then return anything I want and it will create a new array based on the returns. In this case I'm returning the return of the obj.call() basically.

    The then is the callback for when the Promise is resolved so I can handle it's value.

    The return in this case will be something similar to:

    [[{ uudi: '...' }], [{ uuid: '...' }]]
    

    And as you can see it has an array of two arrays with objects inside, so I had to make this array flatten so it would look like this:

    [{ uudi: '...' }, { uuid: '...' } ]
    

    And for this I used this: [].concat(...results) from the then (the resolved single Promise that contains the value from both call.

    This is not that important in C++/Qt, the most important part here is the async part, of how to create something similar to that, that is creating a container of instances, calling each method asynchronously, where each method that has been called will have a heavy operation such as an http request or something like that and return values and then the caller method from the container will have the values from the calls.



  • Anyone to help me with that?


  • Qt Champions 2017

    @yugosonegi

    I wish i could but i have zero idea about javascript. it sounds like QFuture and QtConcurrent but im not sure

    Promise.all(this.storage.map(obj => obj.call())) no idea what this means

    QConcurrent can run a list in threads.

    so you have a list of Biz and you want to call each Bizz function so they all run concurrent?

    The network manager is async
    http://doc.qt.io/qt-5/qnetworkaccessmanager.html



  • @yugosonegi

    If you want to do it something like the way you have done in JS, have you looked at https://github.com/benlau/asyncfuture


  • Lifetime Qt Champion

    Hi,

    Looks like you might be interested by @benlau's AsyncFuture.
    Or QtPromise
    Or Qt-Promise

    WARNING: I haven't tested them but they look like what you are on the hunt for.


  • Qt Champions 2016

    @yugosonegi In C++, the technique to implement async/await is called as coroutines. But unfortunately, that Qt doesn't support yet. You need to seek for 3rd party library's support.

    In case you are satisfied with traditional promise chain in Javascript, you may consider my AsyncFuture project. It turns a QFuture object into a promise-like object, and it could be chained.

    Remarks: The way of handling reject (aka cancel in QFuture) in a promise chain is not identical to Javascript. As it is designed for a multi-threaded actor model. Calling the cancel will cancel everything in the chain.



  • Thank you guys a lot for that, I'll be studying in order to see what is better for me.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.