Reputation: 29
I'm new to the Q library and I have understanding problems with the Q's promises for array methods. I have a array with various key strings to be replaced by a delayed function. After the passed in array got successfully replaced, I need to go on with the now fulfilled array. How do I wait to for the array to be replaced in this case?
Output looks like
key: "p",
text: "Good morning %text%",
inside: key: "p"
text: "Good afternoon user"
inside: key: "p"
text: "This user has to be replaced."
As you can see not all keys got replaced.
Code sample
var object = [];
object.key = "p";
object.text = "Good morning %text%";
object.inside = [];
object.inside.key = "p";
object.inside.text = "Good afternoon %text%";
object.inside.inside = [];
object.inside.inside.key = "p";
object.inside.inside.text = "This %text% has to be replaced.";
goDeep(object, 0);
console.log(object);
function goDeep(data) {
if (data instanceof Object) {
Object.keys(data).forEach(function(key) {
if (data[key] instanceof Object) {
goDeep(data[key]);
} else if (data[key].inside) {
goDeep(data[key].inside);
} else {
var match = scanText(data[key]);
if (match && !(match instanceof Boolean)) {
getServerData(match.input).then (function(response) {
var splitData = data[key].match(/%.*%/)[0].split(",");
for (ii = 0; ii < splitData.length; ++ii) {
splitData[ii] = splitData[ii].trim();
var replaceData = data[key].replace(splitData[ii], response);
// Data gets replaced here
data[key] = replaceData;
};
});
}
}
});
}
}
function scanText(data) {
var match = data.match("(%.*%)", "/g");
if (match) {
return match;
} else {
return false;
}
}
function getServerData(data) {
return Q.delay(1000).thenResolve("user");
}
Upvotes: 0
Views: 1321
Reputation: 21462
First let me correct slightly what do you really want,
Calling an asynchronous function recursively using JavaScript promise
Note: I am note aware of the Q Library, but I am sure it will be similar to others promise implementation
I will try my best to simplify your problem so I will explain it in steps
you need the all
method
Q.all([
getWeather({name:'beirut'}),
getWeather({name:'paris'}),
getWeather({name:'madrid'})
]).then(function(beirut, paris, madrid){
// here I am sure that the 3 methods where completed
});
using array.map
['beirut', 'paris', 'madrid'].map(function(city){ return getWeather(city) });
function getWeather(area) {
// this function should return a promise of the weather response
var deferred = Q.defer();
setTimeout(function () {
deferred.resolve({
name: 'beirut',
children: [{
name: 'sub area'
}, ...]
});
}, 300);
return deffered.promise;
}
function resolveChildren(parentArea, level) {
var deferred = Q.defer();
getWeather(parentArea).then(function (children) {
var promise = Q.all(children.map(function ( /* a sub area */ child) {
// if this a leaf then resolve the child, else go deeper and get the children of this child
// suppose child.isleaf return true if this is a leaf node
if (child.isleaf) {
return child;
}
return resolveChildren(child, level + 1);
}));
promise.then(function (children) {
parentArea.children = children;
deferred.resolve(parentArea);
});
}, function (err) {
// failed to get children for some reason
parentArea.children = null;
deferred.resolve(parentArea);
});
return deffered.promise;
}
Upvotes: 2