A pattern for triggering many async queries

If you are triggering a lot of queries in succession then the normal trigger.onSuccess pattern get very messy. In these case it is best to use an async pattern like so.

if (txtAddTemplateName.value) { // Only execute if form is filled in - Form validation of sorts
(async () => {
  const sourceid = tblSource.selectedRow.data.sourceid // Set variables
  let data1 = await qrySourceUpdate.trigger() 					       const myField = qrySourceUpdate.data.theField[0]
  let data2 = await jsSetView.trigger({additionalScope: {skipSelect: true}})	
if (data2) {
     const myField = data2.theField[0]
     return myField
   } else {
     throw new Error("Query returned no data!")
   }	
  await new Promise(resolve => setTimeout(resolve, 1000))
  await jsSetSourceSelection.trigger({additionalScope: {sourceid: sourceid, assumeSameID: true}})  // Select the updated row if needed
  await jsSourceRowSelect.trigger()  // trigger subtable setups
 })();
}

(from @bradlymathews)

2 Likes

Thanks for the above, v helpful.
One question, when triggering your example from another JavaScript query, how can I run something only if the trigger succeeds and is completed?

For example, if your code above is in a query called `triggerManyAsyncsExample', and I want to run it from another query and console log after it's finished how could I achieve that?

I attempted this with the code below, but it runs the code after triggerManyAsyncsExample.trigger() immediately regardless of the outcome of triggerManyAsyncsExample:

(async () => {
  const triggerAsyns = await triggerManyAsyncsExample.trigger();
  if (triggerAsyns == null) {
      console.log("It failed")
  }
  else{
     console.log("It worked and finished")
  }
  
})();

If I strip the (async () => {...} from your example it seems to give me the behaviour I'm after, does that make sense? So in triggerManyAsyncsExample I have the following

if (txtAddTemplateName.value) { // Only execute if form is filled in - Form validation of sorts
  const sourceid = tblSource.selectedRow.data.sourceid // Set variables
  let data1 = await qrySourceUpdate.trigger() 					       const myField = qrySourceUpdate.data.theField[0]
  let data2 = await jsSetView.trigger({additionalScope: {skipSelect: true}})	
if (data2) {
     const myField = data2.theField[0]
     return myField
   } else {
     throw new Error("Query returned no data!")
   }	
  await new Promise(resolve => setTimeout(resolve, 1000))
  await jsSetSourceSelection.trigger({additionalScope: {sourceid: sourceid, assumeSameID: true}})  // Select the updated row if needed
  await jsSourceRowSelect.trigger()  // trigger subtable setups
}

Following all that I guess my question is, is the (async () => {} wrap required in a query? I get the same effect by just adding await before any ..trigger() calls from what I can tell

1 Like

I think I've answered my own question by following the guide for debugging javascript in retool. It seems all retool js queries are async functions, hence no need to wrap code in (async () => {...} for await to work. But I'm pretty new to promises and async so if anyone can explain it better or correct me please do!

Looking at a query in the chrome dev tools as mentioned in the docs reveals the following:

(async function anonymous(scope
) {
with(scope||{}){ 
// START OF USER CODE 

 }//# sourceURL=isAthenticatedRetoolUser.js
})

1 Like