【问题标题】:Asign component variable with result of async method in a service在服务中使用异步方法的结果分配组件变量
【发布时间】:2022-02-15 23:25:11
【问题描述】:

我正在尝试构建一个应用程序,但我不希望我的组件包含不必要的代码。我想将很多逻辑放入服务中,然后将服务注入到我的组件中。 假设我的组件有一个名为“结果”的变量:

my.component.ts

    .....

    private result:number;

我的服务有一个异步方法:

my.services.ts

    ......
    ......

    getNumberFromApi(){
    callAsync().subscribe( data => {
        console.log('This is the data obtained..'+data);
    })

我希望有机会将参数传递给 getNumberFromApi() 方法:

    getNumberFromAPI(destinationVar:number){
    callAsync().subscribe( data => {
        console.log('This is the data obtained..'+data);
        destinationVar=data;
    })
    

这样在我的组件中我就可以通过这种方式调用该服务的方法:

my.component.ts

    .....

    private result:number;
    myServiceInstance.getNumberFromApi(result);

我知道这是不可能的(可能是因为在响应到达时方法的堆栈已经消失了),但我找不到执行此操作或类似方法的方法。有人可以推荐我一个替代品吗?我想从组件的服务变量中修改,即使使用异步方法,没有除了组件中的方法调用行之外的任何东西。这可能吗?我是否错过了关于 Typescript/Angular 如何在这里工作的关键概念?谢谢。

【问题讨论】:

    标签: angular typescript asynchronous methods parameters


    【解决方案1】:

    您需要从服务中返回 observable 并在组件中订阅它。这样一来,observable 的异步特性将被保留,如果需要,您可以使用不同的参数调用假定的 API 调用。

    服务

    import { Observable } from 'rxjs';
    
    getNumberFromApi(): Observable<any> {
      return callAsync();
    }
    

    组件

    export class SomeComponent implements OnInit {
      someVar: any;
    
      constructor(private someService: SomeService) { }
      
      ngOnInit() {
        this.someService.getNumberFromApi().subscribe({
          next: (value: any) => this.someVar = value,
          error: (error: any) => { }
        });
      }
    }
    

    另一方面,如果组件中的变量someVar仅用于模板中渲染一些数据,则可以跳过组件控制器中的订阅,使用模板中的async管道。

    控制器 (*.ts)

    import { Observable } from 'rxjs';
    
    export class SomeComponent implements OnInit {
      someVar$: Observable<any>;   // <-- dollar sign is only a convention
    
      constructor(private someService: SomeService) { }
      
      ngOnInit() {
        this.someVar$ = this.someService.getNumberFromApi();
      }
    }
    

    模板 (*.html)

    <ng-container *ngIf="(someVar$ | async) as someVar">
      <!-- use `someVar` -->
      {{ someVar }}
    </ng-container>
    

    【讨论】:

    • 啊,请不要以这种方式“静态化”变量。在最终的 Observable 上使用 async 管道在模板中显示其内容。这种事情被认为是强烈的代码气味。
    • @WillAlexander:当您发表此评论时,我正在更新答案。
    • @ruth 订阅回调几乎总是做“太多”,修改行为成为一个艰巨的过程。一个写得很好的管道,操作员做他们应该做的事情,更容易阅读(不仅仅是“美观^^)和推理,并且任何时候你想修改一个实现,你确切地知道在哪里去做吧。
    • @ruth 这是一种“可观察到的卫生”,有点像洗手。它可以帮助您以“更简洁的代码”方式思考。我教订阅回调是代码气味:) OAAB — 运营商总是更好!
    • @imnotthatrobot:是的,当你依赖于一个 observable 的响应时,依赖它的整个范式(比如你的FormGroup)就变成了异步的。如果您希望将对象发送到服务,并将修改后的对象发回,则它需要是可观察的。您需要在服务函数中create an observable,订阅 API 调用,通过 observable 推送响应,并确保完成它。如果这一切听起来很复杂,那就是。通过返回 API 调用并使用 async,您可以轻松实现您的要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多