【问题标题】:Asynchronously POSTing parent-children objects and relationships (recursively?)异步发布父子对象和关系(递归?)
【发布时间】:2021-10-14 11:21:04
【问题描述】:

假设我正在尝试将“家谱”创建为一个 JSON 数组。

所以我有一个Person 对象数组。

每个Person 对象都有一个强制name。每个对象还可以选择有一个 children 字段,其中包含一组其他 Person 对象(也有一个 children 字段 - 所以家谱的“深度”基本上可以永远持续下去。)

如果没有孩子,children 字段将只是一个空数组[]

例如

  const family_name = "The Numbers";
  const family = [{
      name: "1"
      children: [],
    },
    {
      name: "2"
      children: [{
          name: "2 - 1",
          children: [],
        },
        {
          name: "2 - 2",
          children: [{
            name: "2 - 2 - 1",
            children: [],
          }, ],
        }
      ],
    },
    {
      name: "3"
      children: [{
        name: "3 - 1",
        children: [],
      }, ],
    },
  ]

我需要在“孩子”之前发布“父母”。当我发布Person 时,我会在response.data 中获得它的id。此id 需要在直接子项的 POST 中用作parent_id,以便子项与父项关联。

我还需要先发布“family_name”,这将返回family_id。此family_id 将用作parent_id,仅用于最顶层的Persons。

例如

axios.post(FAMILY_URL, {"family_name": family_name})
    .then((response) => {
        // Promise.all() POST 1, 2, and 3 with their "parent_id" as response.data.family_id
        // Promise.all() POST 2-1 and 2-2 with their "parent_id" as 2's response.data.id
        // POST 2-2-1 with its "parent_id" as 2-1's response.data.id
        // POST 3-1 with its "parent_id" as 3's response.data.id
    })

但是如果Person 对象的数量和深度未知,代码会是什么样子?我必须利用递归函数,对吗?

我还想对所有“兄弟姐妹”使用 Promise.all()

【问题讨论】:

  • 您需要发布哪些数据?是否需要在帖子数据中包含children 数组?
  • 尝试查找bfs算法
  • 有效负载应该是 {"name": "", "parent_id": ""} 每当通过 POST 创建 Person 时,都会返回创建的 Personid
  • @MikeK.Shum OP 不是 搜索 虽然 ????
  • 你需要什么样的最终结果?

标签: javascript recursion axios


【解决方案1】:

你想递归地遍历数据结构,一路上积累promise

// fake axios, ignore this bit
const FAMILY_URL="family-url",axios={post:async(a,o)=>(console.log(`POST ${a}`,o),{data:{id:`${a===FAMILY_URL?"":`${o.parent_id}-`}${Math.ceil(100*Math.random())}`}})};

// resolves an individual person by posting their details with a given
// parent ID, then doing the same for any children
const savePerson = async (parent_id, { name, children }) => {
  // get this person's ID
  const { data: { id } } = await axios.post("person-url", {
    name,
    parent_id
  })
  
  return {
    id, // assign the ID for visibility
    name,
    // pass this person's ID as the children's parent
    children: await savePeople(id, children)
  }
}

// resolves an array of people given a "parent ID"
const savePeople = (parent_id, people) =>
  Promise.all(people.map(person => savePerson(parent_id, person)))

// Top-level family helper
const saveFamily = async (family_name, family) => {
  const { data: { id } } = await axios.post(FAMILY_URL, { family_name })
  
  // resolve all the people in the family array
  return savePeople(id, family)
}

// minified
const family = [{"name":"1","children":[]},{"name":"2","children":[{"name":"2 - 1","children":[]},{"name":"2 - 2","children":[{"name":"2 - 2 - 1","children":[]}]}]},{"name":"3","children":[{"name":"3 - 1","children":[]}]}]

saveFamily("Smith", family).then(console.info)
.as-console-wrapper { max-height: 100% !important; }

【讨论】:

    【解决方案2】:

    我会使用 BFS 算法来处理它。 示例:

    function postFamily(family) {
    
        const queue = [];
        queue.unshift(...family);
    
        while (queue.length) {
            const cur = queue.pop();
    
            // HERE IS YOUR LOGIC RELATED TO THE CURRENT NODE
            // FOR EXAMPLE:
            axios.post('*FAMILY URL*', cur);
    
            for (const child of cur) {
                queue.unshift(child);
            }
        }
    }
    

    我不清楚想要的结果,但我很高兴它会有所帮助。祝你有美好的一天!

    【讨论】:

    • 这是一个不错的非递归选项,但您会发现很难跟踪哪个 parent_id 应用于子记录
    猜你喜欢
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多