Query result not in Sync with Components

  • Goal: I want to trigger a query from a form and display either success message or error. The form is located in a Modal.

  • Steps:

  • modal-form has a submit-handler, which calls a script.
  • the script calls trigger() on the query
  • in query-editor I can see the correct API-response
  • the script, however, is not reflecting that
  • To me it looks like the result is not properly propagated to my script
  • Details:

Code for form-handler:

try {
  // importerRerunPost2.reset();
  // importerRerunPost2.invalidateCache();
  //  await new Promise((resolve) => setTimeout(resolve, 500)); // Wait for refresh
  
  const response =  await importerRerunPost2.trigger({ additionalScope: { timestamp: Date.now() } });
  // setTimeout(() => {}, 500); 
  
  console.log("Query finished executing");
  console.log("Response Debug:", response); // <-- undefined
  console.log("Response 2 Debug:", importerRerunPost2.data); // <-- somtimes null, sometimes the value of previous request

  if (!response || !importerRerunPost2.data) {
    console.error("Query executed, but no response returned!", { response, data: importerRerunPost2.data });    
  }
  showSuccess();
} catch(error) {
  showError(error);
}
  

Alternative approaches:

importerRerunPost2.trigger({
    onSuccess: (response) => { ... }
    onError: (error) => { ... }
})

Interestingly, none of those onX-methods gets even called.

The query, importerRerunPost2, is a POST-request with Raw-JSON-payload and json response.
As said, when I submit the form I see always the correct response in the query-view. So the query is working properly.
It also has no caching or special optoins configured.

Example log of the query from within the form-submit-handler:

importerRerunPost2: Object
pluginType: "RESTQuery"
queryRefreshTime: ""
paginationLimit: ""
streamResponse: false
body: Object
lastReceivedFromResourceAt: null
isFunction: false
functionParameters: null
queryDisabledMessage: ""
servedFromCache: false
offlineUserQueryInputs: ""
functionDescription: null
successMessage: ""
queryDisabled: ""
playgroundQuerySaveId: "latest"
workflowParams: null
resourceNameOverride: ""
runWhenModelUpdates: false
paginationPaginationField: ""
workflowRunExecutionType: "sync"
headers: Array(1)
showFailureToaster: false
paginationEnabled: false
query: "admin/rerun"
playgroundQueryUuid: ""
playgroundQueryId: null
error: null
workflowRunBodyType: "raw"
queryRunOnSelectorUpdate: false
runWhenPageLoadsDelay: ""
data: null
isImported: false
showSuccessToaster: false
cacheKeyTtl: ""
requestSentTimestamp: null
cookies: ""
metadata: null
queryRunTime: null
changesetObject: ""
offlineOptimisticResponse: null
errorTransformer: "return data.error"
finished: null
confirmationMessage: null
isFetching: false
changeset: ""
rawData: null
queryTriggerDelay: 0
resourceTypeOverride: ""
enableErrorTransformer: false
showLatestVersionUpdatedWarning: false
paginationDataField: ""
timestamp: 0
enableTransformer: true
showUpdateSetValueDynamicallyToggle: true
version: 2
overrideOrgCacheForUserCache: false
runWhenPageLoads: false
transformer: "// return data
//return res;
return data;"
queryTimeout: 25000
workflowId: null
requireConfirmation: false
type: "POST"
queryFailureConditions: ""
id: "importerRerunPost2"
changesetIsObject: false
enableCaching: false
bodyType: "raw"
offlineQueryType: "None"
queryThrottleTime: 750
updateSetValueDynamically: false
notificationDuration: ""
invalidateCache: "__RETOOL_JS_API__"
trigger: "__RETOOL_JS_API__"
reset: "__RETOOL_JS_API__"
in run script(formModalRerun)

As one can see, there's no

  • data
  • rawData
  • metaData
    set at all.

Ah, and another info: I can see a successful response in my browser's dev-tools, containing correct data as well.

const waitForData = (maxWaitTime = 5000) => {
  const startTime = Date.now();
  
  const checkData = setInterval(() => {
    if (importerRerunPost2.data) {
      clearInterval(checkData); // Stop checking
      console.log("Data available:", importerRerunPost2.data);
      
      // Process response
      const payload = importerRerunPost2.data;
      const statusCode = payload?.metadata?.status ?? payload?.statusCode ?? 500;

      if (Number(statusCode) >= 400) {
        const errMsg = payload?.message ?? `${payload?.data?.title} => ${payload?.data?.detail}`;
        showError(new Error(`Request failed with status ${statusCode}: ${errMsg}`));
        return;
      }

      showSuccess();
    } else if (Date.now() - startTime > maxWaitTime) {
      clearInterval(checkData); // Stop checking after timeout
      console.error("Timeout: Data was never set.");
      showError(new Error("Timeout: Query did not return data."));
    }
  }, 100); // Check every 100ms
};

importerRerunPost2.reset();
importerRerunPost2.invalidateCache();
importerRerunPost2.trigger();

waitForData();

Even with this I see imeout: Data was never set..

I am facing similar issue

Welcome to the community @cwill-smg! Thanks for reaching out.

Based on what you've described, it sounds like you probably need to toggle on the setting shown below. You can find it in the JS query's Advanced settings.

By default, references to globally scoped variables are not updated during the execution of a single JS script. This is the default behavior for performance reasons, but explains why the query results seem to be out of sync.

This fix will hopefully address your issue, as well, @vhasabe! Let us know if either of you have any additional questions. :+1:

@Darren what you mentioned makes complete sense. I had raised this to Retool Support and they provided me a simple tweak to my code and it started to work for me.

let response = await getUserADData.trigger( {
additionalScope: {
uid : searchSelectRecipient.selectedItem.value
},
[// You can use the argument to get the data with the onSuccess function](https://docs.retool.com/queries/guides/javascript/#trigger-a-query)
onSuccess: function(**data**){
console.log("Success");
console.log("Attrs:", **data.attributes**);
},
onFailure: function(error) {
console.error("Error:", error);
// Handle the error here
}
});

In this case onSuccess is getting called consistently.

Not sure how!

1 Like

Glad to hear it, @vhasabe! Were you also able to solve this, @cwill-smg? If not, I'm happy to expand upon what I shared above or answer any additional questions!