Pardon me if I'm repeating an already very asked question but everything I have seen so far doesn't seem recursive to me, or doesn't map to what we are doing, and the subject of promises and deferred seems to be highly complex for me.
I have a "topic tree" that gets built asynchronously as the user expands nodes. This topic is built using an API endpoint that returns the children of a node on click of the (+) button on the topic tree node.
When the user clicks on button I try to recursively load the topic tree elements using a method that looks like this:
function getAssociatedTopics(){
$.get('/topics/curriculum-associations', {guids: [...]})
.then(function(data){
//Process the topic information here
var topicId = /* some processing */;
//Get ancestors of each topic returned
$.get('/topics/getAncestors', {of: topicId})
.then(function(data){
//Process the topic information here
var topicId = /* some processing */;
//Get ancestors of each topic returned
//Rinse repeat as long as we find children of each topic found
});
}).then(function(){
//Expand the nodes
//Select the nodes
});
}
So this is what it should look like but I'm all lost reading the documentation to make sure my stuff executes in the right order... The big problem we are having right now with this structure is that my nodes all load in a concurrent way and then erase the selected nodes, open and close nodes any time and the selection ends up super messy.
I don't want an in depth explanation of promises, nor do I want a full solution, but a general idea how to achieve this.
First thing first, The complexity of fetching what you need should be handled on the server and not the client. Making hundreds of HTTP requests from the client is a performance disaster waiting to happen.
Now for how you'd do it, two important facts:
$.get
returns a promise for the value - that's why you can then
off it, but you can also return it to the outside.then
handler, the promise returns from the then
itself will wait for the inner promise to resolve first. Here is an example illustrating the two points:
$.get("/api").then(function(data) {
return $.get("/api2/" + data.id);
}).then(function(data2) {
// because of point #1, we get the data of the inner call here.
});
Now, for your actual problem:
function getAssociatedTopics(guids) {
// note the `return` here so it can be chained from outside
return $.get('/topics/curriculum-associations', {guids: guids})
.then(function(data){
var topicId = someProcessing(data);
// note we return here. I assume this get returns guids.
return $.get('/topics/getAncestors', {of: topicId})
}).then(function (guids) { // this anonymous function can be inlined
if(guids.length === 0) return; // stop condition
return getAssociatedTopics(guids); // note the recursive call, remember point #2.
});
}
getAssociatedTopics(initial).then(function(){
// all done
});
If you need the results of all the calls, you can chain it off, or you can push to a closure variable array inside the then before the last and access it in the all done handler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With