I'm hoping to get a consensus for how to best handle synchronous queries (those that depend on one to completely finish before executing another). I've had the requirement several times across different apps and I have approached it differently each time.
I have read through the "scripting retool - promises and async queries" documentation, but there's a little voice in my head saying it's outdated and confusing to read.
For example, we want to execute the following steps in order:
let targets = getTargetsFromAPI() // retool query resource
if(targets.length == 0)
return []
endif
let data = getDataFromAPI() // retool query resource
let resultRows = []
foreach targets as target
if(data.property == target.property) {
let resultRow = // create result row object
resultRows.push(resultRow)
}
endforeach
return resultRows;
How would you go about creating a javascript query for this?
Official Documentation
https://docs.retool.com/docs/scripting-retool#promises-and-async-queries
Officially, Retool suggests we use Promises. This code is untested.
let targets = Promise.resolve(getTargetsFromAPI.trigger());
let targetsArray = formatDataAsArray(targets);
if(targets.data.length == 0) {
return [];
}
let data = Promise.resolve(getDataFromAPI.trigger());
let mrsDataData = mrsData.data[0];
let resultRows = [];
_.each(targetsArray, function(target) {
// do processing and push to resultRows
let obj = {'foo': target.bar, 'buzz': target.bazz};
resultRows.push(obj)
});
return resultRows;
** Using then()**
I've used this in some of my apps (past me isn't ever as smart as present me), essentially just chaining together a bunch of .then()
functions. It's not easy to return values though. Admittedly, I don't have a proper example of how this might work with the above situation and I lack the brain power at the moment to convert it.
return something.trigger()
.then(resolve => somethingElse.trigger(resolve))
.then(function(resolve) {
let variable = resolve.data;
});
Using Async/Await
It seems to me this is the modern solution. I'm not a JS expert though. I also note that await
can only be used inside an async
function, so I'm going to wrap all my code in this.
return (async () => {
let targets = await getTargetsFromAPI.trigger();
let targetsArray = formatDataAsArray(targets);
if(targets.data.length == 0) {
return [];
}
let data = await getDataFromAPI.trigger();
let mrsDataData = mrsData.data[0];
let resultRows = [];
_.each(targetsArray, function(target) {
// do processing and push to resultRows
let obj = {'foo': target.bar, 'buzz': target.bazz};
resultRows.push(obj)
});
return resultRows;
})();
I suppose await
is mostly syntactical sugar for Promise.resolve()
, so long as you are in an async
function.
Anyways, I'd love to know what some of you have settled on using for best practice when running synchronous scripts.
Thanks in advance!