【问题标题】:How can I return an object from a recursive function upon completion only?如何仅在完成后从递归函数返回对象?
【发布时间】:2019-06-24 02:16:49
【问题描述】:

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

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

  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;

【问题讨论】:

  • 你在await-ing 一个对象。这与return Promise.resolve({"recipes": ...}); 相同

标签: javascript typescript react-native


【解决方案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% 正确,但您应该能够理解:

【讨论】:

    【解决方案2】:

    我不确定我是否了解这里的具体细节,但您一般可以做的似乎是:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-18
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-29
      • 1970-01-01
      相关资源
      最近更新 更多