仅在完成时如何从递归函数返回对象?

时间:2019-06-24 02:16:49

标签: javascript typescript react-native

我正在调用一个递归函数,该函数将返回一个对象,该对象在每次迭代时都将返回。

我希望仅在递归操作完成后才返回一个对象。而不是每次迭代。

  async fetchRecipe(recipe: any) {
    console.log("fetchRecipe");
    // Start with a root recipe
    let rootRecipe: Recipe = {
      id: recipe.id,
      name: recipe.name,
      ingredients: [],
      childRecipes: []
    }
    // Kick off recursive function
    let result = await this.recursivelyBuildRecipe(rootRecipe);
    console.log("Fetch Recipe returned");
    return result
  }

  async recursivelyBuildRecipe(recipe: Recipe) {
    // fetches using the API
    console.log("recursivelyBuildRecipe");
    this.fetchChildren('http:///recipes/get_children', 'id=' + recipe.id)
      .then(async x => {
        await x.data.children.forEach((async(child: { type: any; ItemId: string; name: string; }) => {
          switch (child.type) {
            case 'ingredient':
              // if ingredient
              let ingredient: Ingredient = {
                id: child.ItemId,
                name: child.name,
                unit: 1
              }
              this.allIngredients.push(ingredient);
              recipe.ingredients.push(ingredient);
              break
            case 'recipe':
              let subRecipe: Recipe = {
                id: child.ItemId,
                name: child.name,
                ingredients: [],
                childRecipes: []
              }
              await this.recursivelyBuildRecipe(subRecipe)
              recipe.childRecipes.push(subRecipe)
              break
          }
        }))
      })
    // This is returning the same amount of times the recursive function is called, I want it to only return once complete.
    var obj = { "recipes": recipe, "ingredients": this.allIngredients }
    return await obj;

2 个答案:

答案 0 :(得分:1)

async recursivelyBuildRecipe(recipe: Recipe) {

  const fetch = await this.fetchChildren('http:///recipes/get_children', 'id=' + recipe.id);
  const asyncRecipe = await fetch.data.children.reduce(async (accPromise,child) => {
    const recipe = await accPromise;
    switch(child.type) {
      case 'ingredient':
        let ingredient: Ingredient = {
          id: child.ItemId,
          name: child.name,
          unit: 1
        }
        this.allIngredients.push(ingredient);
        recipe.ingredients.push(ingredient);
        break;
      case 'recipe':
        let subRecipe: Recipe = {
          id: child.ItemId,
          name: child.name,
          ingredients: [],
          childRecipes: []
        }
        await this.recursivelyBuildRecipe(subRecipe)
        recipe.childRecipes.push(subRecipe)
        break;    
    }

    return recipe;
  },Promise.resolve(recipe));

  return { "recipes": asyncRecipe, "ingredients": this.allIngredients }
}
  1. 请勿混合Promises和async / await语法。从技术上讲,这没有什么不对,但是却非常令人困惑。
  2. 您需要遍历每个检索到的孩子,然后等待他们。我认为,最简单的方法就是减少。尽管这会导致对子项的串行检索-但最终会返回单个对象,并且更易于推理。如果速度不够快,您可以使用Promise.all更好地进行处理,然后自己合并结果。
  3. 我不确定上面的语法是否100%正确,但是您应该可以理解:

答案 1 :(得分:0)

我不确定我是否了解这里的细节,但是看来您通常可以做的是:

  1. await添加this.fetchChildren(否则似乎是因为突变而不是按时获得结果)。
  2. 在递归函数(即isMainCall)中添加第二个布尔参数,仅在第一次(当您开始递归时)传递它,最后将返回值添加到if (isMainCall) return obj