我有JSON对象,我需要清理以$
开头的属性。所以给定的结构下面应该摆脱$aaa
,$bbb
,$ccc
和$eee
:
{
$aaa: "$aaa",
bbb: "bbb",
$ccc: {
$ccc2: "$ccc2",
ccc2a: "ccc2a"
},
ddd: {
$ddd: "$ddd2",
ddd2a: "ddd2a"
},
$eee: "$eee",
fff: "fff"
}
我还想让它以异步方式运行并使用Promises。我无法让这个工作起来。它无法清除$eee
并且不确定我哪里出错了。以下是完整代码和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???");
})
答案 0 :(得分:3)
问题在于这一行:
} else if (typeof obj[i] === "object") return clean$(obj[i]);
一旦它吸引了一个递归的对象,就会返回该递归调用的结果。但是,因为它在那时返回,所以它不会完成对当前级别元素的迭代。
在您的示例中,代码会递归以清除ddd
并返回结果,因此不会继续清除$eee
。
有各种方法来解决这个问题。一种方法是建立一个返回的承诺列表,通过递归调用来清理,只有在它们全部解决后才返回。
答案 1 :(得分:1)
正如@knolleary所说,当你拨打$clean
而不是继续时,你的内部超时功能正在返回。
此时,您的外部封闭已经返回了一个承诺。这个承诺只是等待调用res
的东西,但这个调用永远不会发生。
初始调用正等待这个承诺解决,所以它可以写日志消息“为什么它永远不会到达这里???”。
您必须确保在所有情况下都调用resolve
方法。此外,必须等待$clean
的内部呼叫才能解决。
这是一个有效的解决方案:
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);
})
}