【问题标题】:How to turn recursive function into one that returns a promise on completion如何将递归函数转换为完成时返回承诺的函数
【发布时间】:2019-08-31 05:12:30
【问题描述】:

我有一个循环遍历元素的递归函数,我想在递归函数完成后控制台记录 json 对象。最好是使用承诺还是回调?

这是我当前的代码

function productData(elem) {
    if(elem.hasAttribute("itemprop")) {
      const itemProp =  elem.getAttribute("itemprop");
      const itemText = elem.innerText;
      items[itemProp] = itemText;
      console.log("items", items);
    }

    if (elem.hasChildNodes()) {
      Array.from(elem.children).forEach(function (item) {
        productData(item);
      });
    }
  }

  const items = {}
  // Get All Products on the page
  const product = document.querySelectorAll('[itemtype="http://schema.org/Product"]');

  productData(product[0])

【问题讨论】:

  • 您没有做任何需要使用承诺的异步操作。记录一下
  • @charlietfl 你能给我举个例子吗?
  • 扩展@charlietfl 的评论,承诺适用于非CPU-bound 进程,例如网络、I/O、等待用户输入。您在此函数中所做的一切都受 CPU 限制,因此将其转换为承诺实际上不会在性能方面带来任何好处。
  • 只需调用你的函数并在它记录对象之后立即

标签: javascript recursion callback es6-promise


【解决方案1】:

你没有做任何异步的事情,你既不需要回调也不需要承诺。只需同步返回一个值。

在您当前的代码中,您只需在调用后console.log(item)

更好的方法是在函数内部创建对象并 return 它:

function productData(elem, items={}) {
  if (elem.hasAttribute("itemprop")) {
    const itemProp = elem.getAttribute("itemprop");
    const itemText = elem.textContent;
    items[itemProp] = itemText;
  }

  for (const child of elem.children) {
    productData(child, items);
  }
  return items;
//^^^^^^
}

// Get All Products on the page
const productItems = productData(document.querySelector('[itemtype="http://schema.org/Product"]'));
console.log(productItems);

【讨论】:

  • 我不这样行吗? (我在这里尊重 381k 代表)items 不是正在修改的哈希吗?其更新后的值不会在 for 循环中传递。
  • @JosephCho 一个可变对象,是的。所有(递归)调用的值都被添加到同一个对象中,该对象最终返回。 (诚​​然,这并不像它可能的那样干净。做const items = {}; … Object.assign(items, productData(child)); … return items; 可能会更好)。
【解决方案2】:

如前所述,对于这种特殊情况,您不需要承诺。您可以将您的项目包装在一个闭包中,并在您的递归完成后将其传回。

function callProductData(product, output) {

  function productData(elem, items) {
    if (elem.hasAttribute("itemprop")) {
      const itemProp =  elem.getAttribute("itemprop");
      const itemText = elem.innerText;
      items[itemProp] = itemText;
    }

    if (elem.hasChildNodes()) {
      Array.from(elem.children).forEach(function (item) {
        productData(item);
      });
    }
  }

  productData(product, output);
  console.log(output);
}

var product = document.querySelectorAll('[itemtype="http://schema.org/Product"]'[0];
callProductData(product, {});

【讨论】:

    猜你喜欢
    • 2019-05-25
    • 1970-01-01
    • 2020-01-24
    • 2017-05-09
    • 2023-03-28
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    • 2017-03-24
    相关资源
    最近更新 更多