使用sequelize / nodejs的层次结构查询

时间:2016-07-21 20:45:30

标签: node.js recursion promise sequelize.js

我正在尝试在数据库中加载层次结构。我的表中有一个包含parentId的列,因此每行都可以有一个父列。但我在使用递归和承诺方面遇到了问题。

function read (options) {
  return serviceItemAttributeModel.findOne({
    id: options.id,
    id_organization: options.idOrganization
  })
  .then((attribute) => {
    if (attribute) {
      return loadChildren(attribute, attribute);
    } else {
      return attribute;
    }
  });
}

function loadChildren (root, attribute) {
  return serviceItemAttributeModel.findAll({
    where: {
      id_parent: attribute.id
    }
  })
  .then((attributes) => {
    if (!attributes) {
      return root;
    } else {
      attribute.serviceItemAttributes = [];
      attributes.forEach(function (each) {
        attribute.serviceItemAttributes.push(each);
        return loadChildren(root, each);
      });
    }
  });
}

所以,我调用 来调用 loadChildren 以递归方式尝试加载所有实体(通过查看子项)一个实体)我得到一个未定义的值。有什么想法吗?

我在控制台上也遇到错误:在处理程序中创建了一个promise,但是没有从它返回。

修改

如果这个解决方案在Nosyara帮助之后出现了。谢谢!

function read (options) {
  return serviceItemAttributeModel.findOne({
    where: {
      id: options.attributeId,
      id_organization: options.idOrganization
    }
  })
  .then((attribute) => {
    if (!attribute) {
      return new Promise(function (resolve, reject) {
        resolve(attribute);
      });
    } else {
      return new Promise(function (resolve, reject) {
        attribute.queryCount = 1;
        resolve(attribute);
      })
      .then((attribute) => loadChildren(attribute, attribute));
    }
  });
}

function loadChildren (root, attribute) {
  return new Promise(function (resolve, reject) {
    return serviceItemAttributeModel.findAll({
      where: {
        id_parent: attribute.id
      }
    })
    .then((attributes) => {
      attributes.length = attributes.length || 0;
      root.queryCount = root.queryCount - 1 + attributes.length;
      if (root.queryCount === 0) {
        resolve(root);
      } else if (root.queryCount > 10) {
        let error = new Error('Service attribute hierarchy cant have more then 10 levels');
        error.statusCode = 500;
        reject(error);
      } else {
        attribute.serviceItemAttributes = [];
        attributes.forEach(function (each) {
          attribute.serviceItemAttributes.push(each);
          return loadChildren(root, each).then(() => {
            resolve(root);
          });
        });
      }
    });
  });
}

1 个答案:

答案 0 :(得分:0)

你弄乱了异步调用和返回。您可以将两个函数转换为异步,并通过结果结构进行更新。例如:

function read(...) {
  return new Promise(function (accept, reject) {
    // You code goes here, but instead of return
    accept(resultFromAsyncFunction);
  }); 
}
// ...
read(...).then(function(resultData) { ... });

Here是Promise递归的示例。