承诺的递归

时间:2018-06-28 15:50:27

标签: javascript node.js promise

我在MongoDB中有一个这样的集合

[
  {
    "classId": "1",
    "name": "Input",
    "definition": [
      {
        "property": [
          {
            "classId": "12",
            "name": "One"
          },
          {
            "classId": "8",
            "name": "Comment"
          }
        ]
      }
    ]
  },
  {
    "classId": "8",
    "name": "CommentDetail",
    "definition": [
      {
        "property": [
          {
            "classId": "10",
            "name": "user"
          },
          {
            "classId": "10",
            "name": "message"
          }
        ]
      }
    ]
  },
  {
    "classId": "10",
    "name": "String",
    "definition": []
  },
  {
    "classId": "12",
    "name": "Int",
    "definition": []
  }
]

基于上面的数据库,我有一个模型要显示 数据= {           名称:'',           模板:“       }

对于classId = 1,预期结果为

   {
      "Name": "Input",
      "temlate": "{['One': 'Int','Comment': ['user': 'String','message':'String']]}"
}

我尝试使用递归承诺来实现它。当property []为空时,结果将返回。

这是我的功能:

const getObjectTypeByClassId = (snapshotId, artifactId, objectType) => {

  return artifactDetailModel.find({
      'snapshotId': snapshotId,
      'artifactId': artifactId
    })
    .then(data => {
      let artifact = data[0];
      let definition;
      let definitionData = {};

      return Promise.resolve()
        .then(() => {
          definition = artifact.data.teamworks.twClass[0].definition[0];
          if (!lodash.isUndefined(definition.property)) {
            const listOfProperty = definition.property;
            for (let property of listOfProperty) {
              classId = commonUtil.getArtifactId(property.classRef[0]);
              if (!lodash.isUndefined(classId)) {
                return getObjectTypeByClassId(snapshotId, classId, objectType);
              }
            }
          } else {
            definitionData.nameType = artifact.data.teamworks.twClass[0].elementAttribute.name;
            definitionData.classId = artifact.data.teamworks.twClass[0].elementAttribute.id;
            definitionData.template = bpmMapping.objectType[artifact.data.teamworks.twClass[0].elementAttribute.name];

            return objectTypeModel.create(definitionData)
              .then(obj => {
                const response = {
                  name: objectType.name,
                  isArrayOf: objectType.isArrayOf,
                  nameType: obj.nameType,
                  template: obj.template,
                }
                return response;
              })
          }

        })
    })
}

运行我的函数,响应为

data: {
  Name: Input
  temlate: user: String,
}

请给我建议。

2 个答案:

答案 0 :(得分:0)

我在某种程度上进行了尝试,但是无法正确完成。另外,您的预期输出不是有效的JSON "temlate": {[]},这没有任何意义。 与Promise无关。您必须DFS db数据库并创建预期的输出。这是我现在拥有的Donll收据,您可以按照这些思路考虑。但这远非解决之道。

let mainArray = [
    {
        "classId": "1",
        "name": "Input",
        "definition": [
            {
                "property": [
                    {
                        "classId": "12",
                        "name": "One"
                    },
                    {
                        "classId": "8",
                        "name": "Comment"
                    }
                ]
            }
        ]
    },
    {
        "classId": "8",
        "name": "CommentDetail",
        "definition": [
            {
                "property": [
                    {
                        "classId": "10",
                        "name": "user"
                    },
                    {
                        "classId": "10",
                        "name": "message"
                    }
                ]
            }
        ]
    },
    {
        "classId": "10",
        "name": "String",
        "definition": []
    },
    {
        "classId": "12",
        "name": "Int",
        "definition": []
    }
]

function dfs(root, createdRoot,  fn, level) {

    fn(root,createdRoot, level);

    if(root.definition)/*if definition exists => keep traversing*/
    root.definition[0].property.forEach(function (child) {
        createdRoot.template = createdRoot.template || [];
        let tempObj = {};
        let lookupObj = lookupByClassId(child.classId);
        tempObj[child.name] = lookupObj.name;
        createdRoot.template.push(tempObj);
        dfs(child,tempObj, fn, level + 1);
    });
    else /*if definition doesn't exist, look into the array*/
    {
        createdRoot.template = lookupByClassId(root.classId);
    }
}

function lookupByClassId(classId){
    for(let i=0;i<mainArray.length;++i){
        let element =mainArray[i]
        if(element.classId == classId)
            return element;
    }
}


let root = lookupByClassId(1);
createdRoot ={};

function func1(root, createdRoot, level) {
    createdRoot.name = root.name;
    console.log(root.classId);
}

dfs(root, createdRoot, func1, 0);

答案 1 :(得分:0)

这是互联网上一个人的解决方案。它运作良好。谢谢@Cuong Quach

var MongoClient = require('mongodb').MongoClient;
var database = 'testdequy';
var collection = 'classes';
MongoClient.connect("mongodb://localhost:27017/" + database, function (err, db) {

    findDetails("1").then((r) => {
        console.log("r>>>", r);
    })

    function findDetails(classId) {
        var results = { Name: "", Template: "" };
        var template = {};
        return new Promise((main_resolve, reject) => {
            process(template, "" , classId)

            var works = 0;
            function process(parent, childKey, objectId) {
                return new Promise((resolve, reject) => {
                    db.collection(collection).find({ classId: objectId })
                        .toArray((err, docs) => {
                            if (results.Name == "") {
                                results.Name = docs[0].name;
                            }
                            let objectItem;
                            if (childKey == "")
                                 objectItem = parent;
                            else
                                 objectItem = parent[childKey];

                            console.log("\ndocs", docs[0], objectId, objectItem)
                            if (docs[0].definition.length == 0 || docs[0].definition[0].property == undefined) {
                                let name  = docs[0].name;
                                    parent[childKey] = name;
                                console.log("\nNo child", docs[0],parent, objectItem, docs[0].name)
                                resolve(0);

                            } else {

                                docs[0].definition[0].property.forEach((item) => {
                                    works++;
                                    //console.log("item", item)
                                    let id = item.classId;
                                    let name = item.name;
                                    objectItem[name] = {};
                                    process(objectItem, name, id).then((len)=>{
                                        works--;        
                                        if(len == 0 && works == 0) main_resolve(template);
                                    })

                                })
                                resolve(docs[0].definition[0].property.length)
                            }
                        })
                })
            }
        })

    }

});