2015-06-03 167 views
1

我有我需要清除$開始的屬性的JSON對象。下面就給出這樣的結構應擺脫$aaa$bbb$ccc$eee爲什麼我的帶Promises的遞歸Javascript函數失敗

{ 
    $aaa: "$aaa", 
    bbb: "bbb", 
    $ccc: { 
    $ccc2: "$ccc2", 
    ccc2a: "ccc2a" 
    }, 
    ddd: { 
    $ddd: "$ddd2", 
    ddd2a: "ddd2a" 
    }, 
    $eee: "$eee", 
    fff: "fff" 
} 

我也想讓它異步運行和使用的承諾。無論如何,我都會遇到麻煩。它無法清除$eee,我不知道我錯了哪裏。下面是完整的代碼和:

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

返回一個'的setTimeout裏的任何東西()'絕對沒有。它只是回到定時器引擎的內部。 – jfriend00

回答

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); 
    }) 
} 

Plunkr Fork...

3

的問題是這一行:

} else if (typeof obj[i] === "object") return clean$(obj[i]); 

只要它encouters對象遞歸到,要返回該遞歸調用的結果。但是,因爲它在那個點返回,所以它不會完成對當前級別的元素的迭代。

在你的例子中,代碼遞歸清理ddd並返回結果,所以不會繼續清理$eee

有很多方法可以解決這個問題。一個是建立一個返回的promise的清單,這個清單是遞歸調用的,並且只有在它們全部解決後才返回。