Reputation: 10946
I have JSON object that I need to clean up of properties starting with $
. So given structure below it should get rid of $aaa
, $bbb
, $ccc
and $eee
:
{
$aaa: "$aaa",
bbb: "bbb",
$ccc: {
$ccc2: "$ccc2",
ccc2a: "ccc2a"
},
ddd: {
$ddd: "$ddd2",
ddd2a: "ddd2a"
},
$eee: "$eee",
fff: "fff"
}
I also wanted to make it run asynchronously and use Promises. I'm having trouble however getting this to work. It fails to clean $eee
and am not sure where I am going wrong. Below is full code and plunker is here:
function clean$(obj1) {
var obj = obj1;
return new Promise(function(res, rej) {
setTimeout(function() {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
if (i.match(/^\$/)) {
console.log("delete this " + i);
delete obj[i];
} else if (typeof obj[i] === "object") return clean$(obj[i]);
}
}
res();
}, 1000);
})
}
sample = {
$aaa: "$aaa",
bbb: "bbb",
$ccc: {
$ccc2: "$ccc2",
ccc2a: "ccc2a"
},
ddd: {
$ddd: "$ddd2",
ddd2a: "ddd2a"
},
$eee: "$eee",
fff: "fff"
}
clean$(sample).then(function(res) {
console.log("why it never gets here???");
})
Upvotes: 1
Views: 70
Reputation: 45222
As @knolleary has already said, your internal timeout function is returning when you call $clean
, rather than continuing.
At this point, your outer closure has already returned a promise. This promise is just waiting for something to call res
, but this call never happens.
And the initial call is waiting for this promise to resolve so it can write the log message "why it never gets here???".
You must make sure that the resolve
method is called in all circumstance. Also, something has to wait for the internal call to $clean
to resolve.
Here is a working solution:
function clean$(obj1) {
var obj = obj1;
return new Promise(function(res, rej) {
setTimeout(function() {
var promisesToWaitFor = [];
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
if (i.match(/^\$/)) {
console.log("delete this " + i);
delete obj[i];
} else if (typeof obj[i] === "object") {
promisesToWaitFor.push(clean$(obj[i]));
}
}
};
Promise.all(promisesToWaitFor).then(res);
}, 1000);
})
}
Upvotes: 1
Reputation: 10117
The problem is this line:
} else if (typeof obj[i] === "object") return clean$(obj[i]);
As soon as it encouters an object to recurse into, to returns the result of that recursive call. However, because it returns at that point, it doesn't finish iterating over the elements at the current level.
In you example, the code recurses to clean ddd
and returns the result of that, so doesn't continue on to clean $eee
.
There are various approaches to fixing this. One would be to build up a list of the promises returned be recursive calls to clean, and only return once they have all resolved.
Upvotes: 3