【问题标题】:Assign values to a variable from a Angular subscriber从 Angular 订阅者为变量赋值
【发布时间】:2021-01-31 11:51:35
【问题描述】:

我对 Angular 很陌生。我已经完成了服务和模板,我开始做组件了。我正在尝试从休息服务中分配值(模板)列表。如果用户是管理员,他可以看到所有这些,并且它可以工作。如果用户不是管理员,他只能看到自己的,但我无法让订阅者存储用户的个人资料。 当我尝试分配它时,它不会这样做。我读过这是因为订阅者是异步方法,但我真的找不到解决方案。如何将服务器中的值分配给变量,以便在视图中呈现它?

组件

@Component({
  selector: 'app-plantilla',
  templateUrl: './plantilla.component.html',
  styles: [
  ]
})
export class PlantillaComponent implements OnInit {

  public titulo = 'Colección de plantillas';
  public plantillas: Plantilla[] = [];
  public perfil: Perfil = new Perfil();

  constructor(private plantillaServicio: PlantillaService, private authService: AuthService, private perfilServicio: PerfilService) { }

  ngOnInit(): void {
    if (this.authService.isAuthenticated()) {

      console.log(this.authService.usuario);
      if (this.authService.usuario.rol.id===1 ) {
        console.log("al if");
//this works
        this.plantillaServicio.listar().subscribe(plantillas =>
          this.plantillas = plantillas);
      }else{
        console.log("al else");
//this works
        console.log(this.perfilServicio.ver(this.authService.usuario.id).subscribe(val => console.log(val)));
//this doesn't work
        this.perfilServicio.ver(this.authService.usuario.id).subscribe((val:Perfil)=>this.perfil=val);
//show empty class
        console.log(this.perfil);
      }

    } else {
      console.log("No autenticado");
    }
  }
}

查看

<div
    class="card container"
    *ngFor="let plantilla of plantillas"
>
    <div class="row g-0">
        <div class="col-md-6">
            <h3 class="card-title">
                {{plantilla.id}} - {{plantilla.empresa.nombre}} - {{plantilla.empresa.id}}
            </h3>
        </div>
        <div class="col-md-12">
            <!-- <div class="card-header">{{plantilla.asunto}}</div> -->
            <div class="card-body text-dark bg-light mb-3">
                <h5 class="card-title">{{plantilla.asunto}}</h5>
                <p
                    class="card-text"
                    [innerHTML]=plantilla.texto
                ></p>
            </div>
        </div>
    </div>
</div>

我也在*ngIf="plantillas?.length&gt;0" 视图中尝试过,但控制台显示模板可以未定义。

【问题讨论】:

    标签: angular observable angular2-observables


    【解决方案1】:

    这是人们第一次学习 Rxjs 时很常见的问题。

    console.log(this.perfilServicio.ver(this.authService.usuario.id).subscribe(val => console.log(val)));

    包含整个语句的外部控制台日志只会注销订阅。 不是订阅的结果。内部控制台日志将记录结果的值,因为它在您的 subscribe 块内并完成异步。

    this.perfilServicio.ver(this.authService.usuario.id).subscribe((val:Perfil)=>this.perfil=val); //显示空类 console.log(this.perfil);

    您在此处底部的控制台日志将在您设置订阅块内的变量之前执行

    this.perfilServicio.ver(this.authService.usuario.id)
        .subscribe((val:Perfil)=>{
            this.perfil=val;
            console.log(this.perfil); //This will now work
        });
    

    我强烈建议您学习订阅和可观察的基础知识。 https://www.learnrxjs.io/learn-rxjs/concepts/rxjs-primer

    您的模板可以未定义的原因是因为它们会在您的可观察对象完成之前呈现。因此,您需要通过将任何异步代码包装在(例如)*ngIf="!asyncVariable" 中来了解这一点。

    或者你可以使用如下的角度异步模板

    您的 html 将使用异步管道 https://angular.io/guide/observables-in-angular

    *ngFor="let plantilla of plantillas | async"
    

    您的 ts 文件不会订阅 observable。它只会分配它。订阅通过角异步管道在引擎盖下进行。

    this.plantillas = this.plantillaServicio.listar();
    

    【讨论】:

    • 谢谢詹姆斯,我一直在阅读您指向我的文档。我更喜欢第一个链接中的那个,但它们都没有帮助解决我的问题。尽管我认为您在变量已满之前打印是正确的,但至少它在浏览器控制台中是这样显示的,无序。异步管道也不会,它会引发大量错误。
    • 它显示了什么?你尝试了什么代码?
    【解决方案2】:

    我的解决办法是这样的:

    正如詹姆斯所说,关键是要理解异步性。在执行订户时,可能需要一点或很多时间,但无论如何都需要时间,执行下一条指令。如果该指令依赖于订阅者的结果,它将无法按预期工作。

    需要注意的是,每个订阅者都有三个参数,事件、错误和完成。在完成块内,可以执行其余的指令,但总是在这个块内,而不是在它或订阅者之外。为此,我需要一个更多的订阅者,一个链接的订阅者。 第一个订阅者检索配置文件,第二个订阅者检索植物,这是我真正想要的。而视图代码我也不必碰它。

    @Component({
      selector: 'app-plantilla',
      templateUrl: './plantilla.component.html'
    })
    export class PlantillaComponent implements OnInit {
    
      public titulo = 'Colección de plantillas';
      public plantillas: Plantilla[] = [];
      public perfil: Perfil = new Perfil();
      private empresa: Empresa = new Empresa ();
    
      constructor(private plantillaServicio: PlantillaService,
        private authService: AuthService,
        private perfilServicio: PerfilService,
        private empresaServicio: EmpresaService) { }
    
      ngOnInit(): void {
        if (this.authService.isAuthenticated()) {
    
          console.log(this.authService.usuario);
          if (this.authService.usuario.rol.id === 1) {
            console.log("al if");
            this.plantillaServicio.listar().subscribe(plantillas => this.plantillas = plantillas);
          } else {
            console.log("al else");
    //call to old suscriptor
            this.setPerfil(this.authService.usuario.id);
          }
        } else {
          console.log("No autenticado");
        }
      }
    
    // old suscriptor but modified
      setPerfil(id: number): void {
        this.perfilServicio.ver(this.authService.usuario.id)
          .subscribe((val: Perfil) => {
            this.perfil = val;
            console.log(val);
          }, (err) => {
            console.log(err)
          }, () => {
            console.log('perfil complete!');
    //call to new suscriptor
            this.setPlantillas(this.perfil.id);
          });
      }
    
    //new suscriptor
      setPlantillas(id: number): void {
        this.plantillaServicio.listarPorEmpresa(id)
        .subscribe((val: Plantilla[]) => {
          this.plantillas=val;
          console.log(val);
        }, (err) => {
          console.log(err)
        }, () => {
          console.log('plantillas complete!');
        });
      };
    }
    

    【讨论】:

      猜你喜欢
      • 2020-02-02
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 2021-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多