I'm struggling with old data being displayed when queries take longer than they should and return late or out of order.
This is NOT about how to call an async function or get query results. It's about how to either cancel/abort an async call or what tactic makes the best programming strategy for detecting out of-order query results as a result of multiple async processes.
Context: in one of my Svelte components, in the script section I have an await call that wraps around the fetch API to get data from a database. Simplified, my component looks like this:
<script>
export let modelEntityId, entityNode, accessorDelegates
let data
async function runQuery() {
const newQuery = new Query()
// set up query params
newQuery.setRequest({statement: entityNode.statementName,
columns: entityNode.columns,
filters: {[entityNode.entityIdColumn]: modelEntityId}})
// submit the query by calling a top-level function in App.svelte which uses the fetch API
if (await accessorDelegates.getQueryData(newQuery)) {
// assign query results to local component variable
data = newQuery.response.data
}
}
$: modelEntityId && runQuery()
</script>
<!--- display data --->
Now modelEntityId
provides my data key, determining which record I'll pull from the database, and this comes down via prop into my component. When the user selects a different entity, the prop reacts, calls the async runQuery
function, which initiates the query then sits on await accessorDelegates.getQueryData
awaiting results. When the results return, they are assigned to a local variable and that reacts the DOM below and displays.
But I have some queries that need tuning... they take a minute, and if the user loses interest and clicks away to a different entity (modelEntityId
changes), a new query is executed to get that data, while the old query is still out there somewhere. Then the old query completes, and it is reacting the DOM and displaying its data while the user thinks they should be seeing data from the new query. Worse, sometimes the new query returns first and displays, then a bit later the older query returns and overwrites the newer display values with the older data.
I'm having trouble understanding this. Is it due to async? Am I ending up with two processes in a race condition that can both react the DOM the user sees depending on which query finishes first?
If this is the case, what's the best way to deal with this? I would not want the user to see the first query's results if they've abandoned it and gone on to a new query. I can certainly do a manual check of the filter values I requested and compare them with the values retrieved to make sure they match, but I'm interested to know if there's a better way. Should I be looking into how to cancel/abort any old async function calls whenever the function is called anew?