I'm pretty new to using APIs, so please forgive me if this is really trivial.
There are two GET requests I want to use:
/workflow/search
will allow me to get an entire list of workflows along with their data (i.e. the workflow id)./workflow/{workflowId}
will allow me to get a specific workflow with more details.I currently have importedWorkflows
in my data function, which is populated with what I get from the /workflow/search
call. If I want to know more information about a workflow, then I would want to call /workflow/{workflowId}
.
However, this has been really difficult, especially since I'm using Jquery to get the JSON data.
$.getJSON(dataURL, function(data) {
self.importedWorkflows = data.results;
});
Since it's all asynchronous, I really just want access to the information found with /workflow/{workflowId}
whenever it's ready.
This was my attempt in making that happen:
I have computed array called importedWorkflowDefinitions
that goes through all the workflows found with /workflow/search
and makes the /workflow/{workflowId}
call for every workflow. I store the returned JSON data for every call in the computed array. Then, I use a method called generateWorkflowById()
to lookup the workflow JSON in importedWorkflowDefinitions
.
However...
In my Vue application, I have a table made with the v-for directive.
<tbody v-for="workflow in workflowsOnPage">
<tr class="expandable-row" :id="workflow.workflowId">
<td>{{ generateWorkflowById(workflow.workflowId).workflowName }}</td>
<td>{{ workflow.workflowId }}</td>
<td>{{ workflow.status }}</td>
<td class="text-align-right">{{ workflow.startTime }}</td>
<td class="text-align-right">{{ workflow.endTime }}</td>
...
Note: workflowsOnPage
is a computed JSON array that divides importedWorkflows
.
So, what essentially has been happening is that the table will render without the generateWorkflowById(workflow.workflowId).workflowName
value, because the first call /workflow/search
had not finished. Also, even though workflowDefinitions
is computed and will change when the /workflow/search
call is done, the table has already finished rendering and won't run the generateWorkflowById(..)
method again.
Is there a way to render information found with /workflow/{workflowId}
call onto the table without this race happening with all my data?
By the way, I'm working with Netflix Conductor, so if there are better API calls or a different way to have access to all the details pertaining to a workflow so I don't have to make these dependent API calls, please let me know!
Thank you!
There's a couple of things here...
Here, a different approach would be to fetch all your data in the created
hook of your component and show loading indicators for parts that are still coming together
export default {
data: () => ({
importedWorkflows: []
}),
computed: {
workflowsOnPage () {
return .... // whatever you do to importedWorkflows to "divide" them
}
},
async created () {
const res = await fetch('/workflow/search')
const workflows = (await res.json()).results
// assign the new array values once all fetches are resolved
this.importedWorkflows = await Promise.all(workflows.map(async workflow => {
const res = await fetch(`/workflow/${workflow.workflowId}`)
const details = await res.json() // assuming this is correct
return {
...workflow,
details
}
}))
}
}
<p v-if="workflowsOnPage.length === 0">Loading...</p>
<!-- snip -->
<!-- this won't render until the "workflowsOnPage" array has elements -->
<tbody v-for="workflow in workflowsOnPage">
<tr class="expandable-row" :id="workflow.workflowId">
<td>{{ workflow.details.workflowName }}</td>
<td>{{ workflow.workflowId }}</td>
<td>{{ workflow.status }}</td>
<td class="text-align-right">{{ workflow.startTime }}</td>
<td class="text-align-right">{{ workflow.endTime }}</td>
<!-- etc -->
</tr>
</tbody>
Note that I've loaded the extra details from /workflow/{workflowId}
into the details
property of each workflow
object returned by /workflow/search
.