为来自 Angular 订阅者的变量赋值

时间:2021-01-31 11:51:35

标签: angular observable angular2-observables

我对 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>0" 视图中尝试过,但控制台显示可以取消定义模板。

2 个答案:

答案 0 :(得分: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

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

或者您可以使用如下所示的 Angular 异步模板

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

*ngFor="let plantilla of plantillas | async"

您的 ts 文件不会订阅 observable。它只会分配它。订阅发生在带有角度异步管道的引擎盖下。

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

答案 1 :(得分:0)

我的解决方案是这样的:

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

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

@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!');
    });
  };
}
相关问题