Basically, I'm trying to set up a tree, where each node has a reference to it's parent. I've tried the following:
function insert_node(node_data, parent_id) {
var deferral = Q.defer()
deferral.promise.then(async_create_node(node_data, parent_id))
deferral.promise.then(function(parent_node_id) {
var deferral = Q.defer()
node_data.children.forEach(function(node) {
deferral.promise.then(insert_node(generate_node_data(node), parent_node_id))
}
return deferral.resolve();
}
return deferral.resolve();
}
function insert_all_nodes() {
var deferral = Q.defer();
deferral.promise.then(insert_node(top_node));
deferral.resolve()
}
The issue is that I need it to only create one node at a time, and wait until that node is done being created, and only then move on to the next one. The way it's working now, it will start creating a new node before the first one is finished, which causes problems. I've tried nesting the functions in several ways, and using Q.fcall(). I need the id that async_create_node returns for multiple child nodes, otherwise I'd just use recursion.
The combination of asynchronicity and recursion makes this slightly tricky to get one's mind round.
Firstly, we must be sure that async_create_node() returns a promise, otherwise there's no basis on which to acknowledge its asynchronicity and the whole enterprise would need to be synchronous.
Secondly, let's assume that, at each level (particularly the topmost level), we need to know not only that that level's node has been created but also that the whole tree below it has been created.
Then, you should be able to do something like this :
function insert_node(node_data, parent_id) {
var dfrd = Q.defer();
async_create_node(node_data, parent_id).then(function(id) {
var promises = [];
node_data.children.forEach(function(node) {
promises.push(insert_node(generate_node_data(node), id));
});
Q.all(promises).then(dfrd.resolve);
});
return dfrd.promise;
}
function insert_all_nodes() {
return insert_node(top_node_data, top_node_id);
}
That's all off the top of my head, untested.
To create sibling nodes sequentially, you can build a .then() chain in the forEach loop as follows :
function insert_node(node_data, parent_id) {
var dfrd = Q.defer();
async_create_node(node_data, parent_id).then(function(id) {
var p = Q.defer().resolve().promise;//Seed promise on which to build a then() chain.
node_data.children.forEach(function(node) {
p = p.then(function() {
insert_node(generate_node_data(node), id);
});
});
p.then(dfrd.resolve);
});
return dfrd.promise;
}