Retool’s query triggers rely on a callback-based API, which can sometimes catch developers off guard—especially if you’re used to using the more modern Promise
/async
/await
patterns. In fact, I’ve seen a few bug reports from folks expecting their queries to throw exceptions when they fail (like a Promise would), only to discover that Retool’s callbacks behave differently.
Why Promises
Traditionally, developers relied on callbacks to handle asynchronous tasks. While callbacks work fine for small scripts, they can quickly become cumbersome with more complex workflows, leading to “callback hell” or deeply nested code. Promises (and, later, async/await) help solve this problem by:
- Flattening nested code (no more deeply nested callbacks).
- Enabling
try/catch
error handling with async/await. - Making asynchronous code look and behave more like synchronous code.
Not a Big Problem—But an Easy Fix
Most Retool scripts are small enough that callback code doesn’t get too unwieldy. However, if you prefer the cleaner syntax of Promises or if you have a more complex script, you can easily convert query triggers into Promises with just a tiny helper function:
function triggerAsPromise(query, additionalScope = null) {
return new Promise((resolve, reject) => query.trigger({
onSuccess: data => resolve(data),
onFailure: error => reject(error),
additionalScope,
}))
}
You can preload this function and then call your queries via await
or .then()
just like any other promise-based function.
Example Usage
1. Basic Usage
try {
const result = await triggerAsPromise(myQuery)
console.log("Success!", result)
} catch (error) {
console.error("Something went wrong:", error)
}
2. You can also pass additionalScope
try {
const data = await triggerAsPromise(myQuery, { city: "New York" })
console.log("Received data for city:", data)
} catch (error) {
console.error("Failed to fetch data:", error)
}
3. Or combine Multiple Queries with Promise.all
try {
const [resultA, resultB] = await Promise.all([
triggerAsPromise(queryA),
triggerAsPromise(queryB, { userId: 123 }),
])
console.log("Both queries succeeded:", resultA, resultB)
} catch (error) {
console.error("Error from either Query A or B:", error)
}