如何递归迭代文件的树结构以使用Promises获取?

时间:2014-11-30 11:07:05

标签: javascript recursion promise bluebird

我有一个我想要加载的文件结构(所有json)。获取的文件将显示是否还有需要获取的子项。

目前我有这个:

    storage.digestType = function (my_storage, my_type) {
      var type_list, blocker;

      type_list = [];
      blocker = new Promise(function (resolve) {

        function handler(my_pass_store, my_type_list, my_pending_parent) {
          return fetchDefinition(my_pass_store, my_type_list)
            .then(function (my_result_list) {
              var i, len, iter, kids, pending_list, pender;

              // kids blockers will go in here
              pending_list = [];

              for (i = 0, len = my_result_list.length; i < len; i += 1) {
                iter = my_result_list[i];
                kids = iter.child_portal_type_list;

                // update type_list
                type_list.push(iter.base_portal_type);

                // there are kids, so call handler on them
                if (kids) {
                  pender = new Promise(function (pending_resolve) {
                    handler(my_storage, kids, pending_resolve);
                  });
                  pending_list.push(pender);
                }

                return Promise.all(pending_list)
                  .then(function (response_list) {
                    my_pending_parent(type_list);
                  });
              }
            });
        }

        // start with first call
        return handler(my_storage, [my_type], resolve);
      });

      return blocker
        .then(function () {
          console.log("DONE DONE");
          console.log(type_list);
        });
    }

我的文件结构是n级深度。我正在调用一个名为fetchDefinition的方法,它将返回如下内容:

{
  "portal_type": "portal_type_definition",
  "base_portal_type": "portal_index",
  "child_portal_type_list": null
}

我正在将base_portal_type添加到我的type_list参数(日志),然后我正在检查child_portal_type_list null 还是像 ["foo", "bar"...] 即可。在后一种情况下,我将数组传递给handler的新调用。

我的问题是,我似乎第一次失败child_portal_type_list=null。这似乎解决了所有悬而未决的阻截者,我早早就完成了。

问题
如何正确设置阻止承诺并将其传递给递归调用?

谢谢!

1 个答案:

答案 0 :(得分:0)

坐在这个方法前面已经有一段时间了,我意识到我之后将return语句放在我的for-loop vs中。这就是解决方案被提前触发的原因。现在很容易解决...这是正确的代码,以防其他人需要这样的东西:

storage.digestType = function (my_storage, my_type) {
  var type_list, blocker;

  type_list = [];
  blocker = new Promise(function (resolve) {

    function handler(my_pass_store, my_type_list, my_pending_parent) {
      return fetchDefinition(my_pass_store, my_type_list)
        .then(function (my_result_list) {
          var i, len, iter, kids, pending_list, pender;

          // kids blockers will go in here
          pending_list = [];

          for (i = 0, len = my_result_list.length; i < len; i += 1) {
            iter = my_result_list[i];
            kids = iter.child_portal_type_list;

            // update type_list
            type_list.push(iter.base_portal_type);

            // there are kids, so call handler on them
            if (kids) {
              pender = new Promise(function (pending_resolve) {
                handler(my_storage, kids, pending_resolve);
              });
              pending_list.push(pender);
            }
          }

          // THE RETURN STATEMENT SHOULD BE OUTSIDE THE LOOP!
          return Promise.all(pending_list)
            .then(function (response_list) {
              my_pending_parent(type_list);
            });
        });
    }

    // start with first call
    return handler(my_storage, [my_type], resolve);
  });

  return blocker
    .then(function () {
      console.log("DONE DONE");
      console.log(type_list);
    });
}