我正在try 遵循一个教程在Angular .

Issue #1: 当使用2个服务,即recipe. service. ts(在本地处理数据操作)和data—storage. service. ts(在firebase中存储数据)时会出现问题.当从data-storage.service.ts调用getRecipes()方法时,只返回默认值而不是更新的值.

图像更好地澄清.Browser Dev Tools Console 点击"保存数据"按钮的点在上图中以红色标记.

Issue #2: 教师使用这个. recipes. slice()来提取数据,但如果我使用它,新添加或删除的值不会被反映出来.为了查看更改,我使用了this. recipes. slice(0,this.recipes.length).我的问题是,如果长度改变了,什么是正确的方式来反映它.

内容recipe.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

import { Recipe } from './recipe.model';
import { Ingredient } from '../shared/ingredient.model';
import { ShoppingListService } from '../shopping-list/shopping-list.service';

@Injectable()
export class RecipeService {
  recipesChanged = new Subject<Recipe[]>();

  // private recipes: Recipe[] = [];
  private recipes: Recipe[] = [
    new Recipe(
      'Tasty Schnitzel',
      'A super-tasty Schnitzel - just awesome!',
      'https://upload.wikimedia.org/wikipedia/commons/7/72/Schnitzel.JPG',
      [
        new Ingredient('Meat', 1),
        new Ingredient('French Fries', 20)
      ]),
    new Recipe('Big Fat Burger',
      'What else you need to say?',
      'https://upload.wikimedia.org/wikipedia/commons/b/be/Burger_King_Angus_Bacon_%26_Cheese_Steak_Burger.jpg',
      [
        new Ingredient('Buns', 2),
        new Ingredient('Meat', 1)
      ])
  ];

  constructor(private slService: ShoppingListService) {}

  setRecipes(recipes: Recipe[])
  {
    this.recipes = recipes;     
    this.recipesChanged.next(this.recipes.slice(0,this.recipes.length));
    console.log('setRecipes');
    console.log(this.recipes.slice(0,this.recipes.length));
  }

  getRecipes() 
  {
    console.log('getRecipes');
    console.log(this.recipes.slice(0,this.recipes.length)); 
    return this.recipes.slice(0,this.recipes.length);
  }

  getRecipe(index: number) 
  {
    console.log('getRecipe'); 
    return this.recipes[index];
  }

  addIngredientsToShoppingList(ingredients: Ingredient[]) 
  {
     
    this.slService.addIngredients(ingredients);
    console.log('addIngredientsToShoppingList');
    console.log(this.recipes.slice(0,this.recipes.length));
  }

  addRecipe(recipe: Recipe) 
  {    
    this.recipes.push(recipe);
    this.recipesChanged.next(this.recipes.slice(0,this.recipes.length));
    console.log('addRecipe');
    console.log(this.recipes.slice(0,this.recipes.length));
  }

  updateRecipe(index: number, newRecipe: Recipe) 
  {
    
    this.recipes[index] = newRecipe;
    this.recipesChanged.next(this.recipes.slice(0,this.recipes.length));
    console.log('updateRecipe'); 
    console.log(this.recipes.slice(0,this.recipes.length));
  }

  deleteRecipe(index: number) 
  {
     
    this.recipes.splice(index, 1);       
    this.recipesChanged.next(this.recipes.slice(0,this.recipes.length));
    console.log('deleteRecipe');
    console.log(this.recipes.slice(0,this.recipes.length));
  }
}

内容data-storage.service.ts

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { RecipeService } from "../recipes/recipe.service";
import { Recipe } from "../recipes/recipe.model";
import { map, tap } from 'rxjs/operators';

@Injectable({providedIn: 'root'})
export class DataStorageService 
{
    constructor(private http: HttpClient, private recipeService: RecipeService)
    {

    }

    storeRecipes()
    {
        const recipes = this.recipeService.getRecipes();
        console.log('storeRecipes');
        console.log(recipes);
        // this.http.put('https://....../recipes.json', recipes)
        // .subscribe(response => console.log(response));
    }

    fetchRecipes()
    {
        return this.http
        .get<Recipe[]>(
          'https://....../recipes.json'
        )
        .pipe(
          map(recipes => {
            return recipes.map(recipe => {
              return { ...recipe, ingredients: recipe.ingredients ? recipe.ingredients : [] };
            });
          }),
          tap(recipes => {
            this.recipeService.setRecipes(recipes);
          })
        )
    }
}

先谢谢你.

我希望data-storage.service.tsrecipe.service.ts得到更新值.是否有任何单独的对象是由我的任何错误创建的?

推荐答案

更新

问题在于创建两个RecipeService个实例

  1. app.module.ts中有一个recipe service的实例,这是应该定义它的正确位置,因为它需要和数据服务处于同一级别!

  2. 问题是由于当RecipeService被添加到Recipes.component.tsproviders数组时创建的第二个实例,这创建了第二个实例,该实例使用所有最新值更新,但数据服务不可见,因为DI采用的是组件实例而不是模块实例

Recipes.component.ts

import { Component, OnInit } from '@angular/core';
import { Recipe } from './recipe.model';
import { RecipeService } from './recipe.service';

@Component({
  selector: 'app-recipes',
  templateUrl: './recipes.component.html',
  styleUrl: './recipes.component.css',
  // providers: [RecipeService] // <- this created a separate instance and removing it fixed the issue!
})
export class RecipesComponent implements OnInit {
...

Stackblitz Demo (might not work due to commit issues)


数组作为引用存储在内存中,而不是实际值.

当你从数组中推送或删除任何元素时,try 使用array de-structuring更新数组引用,以便新引用中包含最新的元素,这可能会解决你的问题!

addRecipe(recipe: Recipe) 
  {    
    this.recipes.push(recipe);
    this.recipes = [...this.recipes];  // <- changed here!        
    this.recipesChanged.next(this.recipes);
    console.log('addRecipe');
    console.log(this.recipes);
  } 

  deleteRecipe(index: number) 
  {
     
    this.recipes.splice(index, 1);       
    this.recipes = [...this.recipes];  // <- changed here!
    this.recipesChanged.next(this.recipes);
    console.log('deleteRecipe');
    console.log(this.recipes);
  }

Typescript相关问答推荐

在TypScript手册中可以视为接口类型是什么意思?

在类型内部使用泛型类型时,不能使用其他字符串索引

找不到带名称的管道''

在Typescribe中,extends工作,但当指定派生给super时出错""

为什么从数组中删除一个值会删除打字错误?

根据上一个参数值查找参数类型,也返回类型

TypeScript:在作为参数传递给另一个函数的记录中对函数的参数实现类型约束

在TypeScrip中分配回调时,参数的分配方向与回调本身相反.为什么会这样呢?

为什么我的Set-Cookie在我执行下一次请求后被擦除

隐式键入脚本键映射使用

为什么我的一个合成函数不能推断类型?

保护函数调用,以便深度嵌套的对象具有必须与同级属性函数cargument的类型匹配的键

转换器不需要的类型交集

类型';字符串|数字';不可分配给类型';未定义';.类型';字符串';不可分配给类型';未定义';

如何提取具有索引签名的类型中定义的键

通过辅助函数获取嵌套属性时保留类型

为什么类方法参数可以比接口参数窄

使用嵌套属性和动态执行时,Typescript 给出交集而不是并集

当并非所有歧视值都已知时,如何缩小受歧视联盟的范围?

将函数签名合并到重载中