【问题标题】:Why my recursive Javascript function with Promises fails为什么我的带有 Promises 的递归 Javascript 函数失败了
【发布时间】:2015-06-04 07:13:37
【问题描述】:

我有 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???");
})

【问题讨论】:

  • 返回setTimeout() 中的任何内容绝对没有任何作用。它只是返回到计时器引擎的内部。

标签: javascript recursion promise


【解决方案1】:

问题出在这一行:

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

一旦遇到要递归的对象,就返回该递归调用的结果。但是,因为它在该点返回,所以它没有完成对当前级别的元素的迭代。

在您的示例中,代码递归清理ddd 并返回结果,因此不会继续清理$eee

有多种方法可以解决此问题。一种方法是建立一个返回的promise列表,递归调用clean,并且只有在它们全部解决后才返回。

【讨论】:

    【解决方案2】:

    正如@knolleary 已经说过的,当您调用$clean 时,您的内部超时函数正在返回,而不是继续。

    此时,您的外部闭包已经返回了一个承诺。这个promise只是在等待调用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...

    【讨论】:

      猜你喜欢
      • 2020-08-23
      • 2022-11-29
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-16
      相关资源
      最近更新 更多