【问题标题】:Recursive function with Promises带有 Promise 的递归函数
【发布时间】:2017-12-30 16:27:45
【问题描述】:

我正在使用一个返回评论对象的 api,cmets 可以有孩子也是评论对象。

我正在尝试使用递归检索整个评论线程,但它不起作用,只要评论没有孩子,函数就会提前结束并且返回的结果不包含整个评论线程。

如何更改函数,以便在检查所有 cmets 没有孩子后进行解析。

api返回的评论对象示例

{
  "id": 16020433,
  "kids": [
    16021684,
    16021721,
    16021659
  ],
  "title": "Why isn't literally every train automated?",
  "type": "story"
}

这是我的代码:

function getCommentsWrapper(id) {
  let comments = [];
  return new Promise((resolve, reject) => {
    function recurseComments(id) {
      let url = `https://hacker-news.firebaseio.com/v0/item/${id}.json`;
      let comment = {};
      fetch(url)
        .then(response => response.json())
        .then(cmt => {
          comment = cmt
          comments.push(comment);
          if (comment.kids) {
            comment.kids.forEach(id => recurseComments(id));
          } else {
            resolve(comments)
          }
        })
    }

    recurseComments(id);
  })



  // call the function with
  getCommentsWrapper("16033496")
    .then(result => console.log(result));

【问题讨论】:

    标签: javascript promise


    【解决方案1】:

    您可以使用调用计数技术,如下面的代码所示。或者您可以使用诸如Bluebrid 之类的库。我认为他们有很多选择。

    我认为 Promise.all 也可以满足要求,但根据我过去的经验,在处理 Promise 数组时向 Promise.all 添加新的 Promise 并不可靠。

    function getCommentsWrapper(id) {
    
      var promises = [];
      let count = 0;
    
      let futureValue = new Promise((resolveAll, rejectAll)=>{
          let comments = [];
          let call = (id) => {
            count++;
            new Promise((resolve, reject) => {
              let url = `https://hacker-news.firebaseio.com/v0/item/${id}.json`;
              let comment = {};
              fetch(url)
                .then(response => response.json())
                .then(cmt => {
                  comment = cmt
                  comments.push(comment);
                  if (comment.kids) {
                    comment.kids.forEach(id => call(id));
                  }
    
                  resolve();
                  count--;
                  if(count < 1){
                    resolveAll(comments);
                  }
                })
            });
          };
    
          call(id);
      });
      return futureValue;
    }
    
    
    // call the function with
    getCommentsWrapper("16033496")
      .then(result => console.log(result));
    

    【讨论】:

    • 感谢添加 count 变量来跟踪 cmets 嵌套的次数,效果很好。创建额外的 Promise 以包裹 Promise 的原因是什么?
    • 因此,您可以遵循代码中的 then 模式,例如 getCommentsWrapper。否则,您将需要创建回调。
    猜你喜欢
    • 2017-03-25
    • 2021-02-03
    • 2015-07-17
    • 1970-01-01
    • 2015-10-28
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 2016-05-26
    相关资源
    最近更新 更多