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 thecall
method from the registered instances asynchronously.Looking at the
call
method from the classesFoo
andBar
you will notice anasync
keyword that means that we can use the keywordawait
inside of that method. In this case I usedawait 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 thePromise
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 thethen
(the resolved singlePromise
that contains the value from bothcall
.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
call
s. -
Anyone to help me with that?
-
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 -
If you want to do it something like the way you have done in JS, have you looked at https://github.com/benlau/asyncfuture
-
Hi,
Looks like you might be interested by @benlau's AsyncFuture.
Or QtPromise
Or Qt-PromiseWARNING: I haven't tested them but they look like what you are on the hunt for.
-
@yugosonegi In C++, the technique to implement
async
/await
is called ascoroutines
. 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
(akacancel
in QFuture) in a promise chain is not identical to Javascript. As it is designed for a multi-threaded actor model. Calling thecancel
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.