最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

angular - Http call is running in loop when using async in template - Stack Overflow

programmeradmin2浏览0评论

I have a problem and I'm looking for a solution. In a standalone component (Angular 19) with OnPush detection in the template I want to read data from observable:

@Component({
  selector: 'app-profile',
  imports: [AsyncPipe],
  template: `
    @let userData = oidcService.getUserData() | async;
    @let apiUserData = usersService.usersGet(userData.sub) | async;
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProfileComponent {
  public readonly oidcService = inject(OidcSecurityService);
  public readonly usersService = inject(UsersService);
}

UsersService:

@Injectable({
  providedIn: 'root',
})
export class UsersService {
  private readonly urlBase = `${environment.apiUrl}/users`;
  private readonly httpClient = inject(HttpClient);

  public usersGet(id: string): Observable<UserEntity> {
    return this.httpClient.get<UserEntity>(`${this.urlBase}/${id}`);
  }
}

The problem is that apiUserData gets into a loop of calls instead of asking only once. userData works fine, but it returns data from the service without http. Why does this happen?

I have a problem and I'm looking for a solution. In a standalone component (Angular 19) with OnPush detection in the template I want to read data from observable:

@Component({
  selector: 'app-profile',
  imports: [AsyncPipe],
  template: `
    @let userData = oidcService.getUserData() | async;
    @let apiUserData = usersService.usersGet(userData.sub) | async;
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProfileComponent {
  public readonly oidcService = inject(OidcSecurityService);
  public readonly usersService = inject(UsersService);
}

UsersService:

@Injectable({
  providedIn: 'root',
})
export class UsersService {
  private readonly urlBase = `${environment.apiUrl}/users`;
  private readonly httpClient = inject(HttpClient);

  public usersGet(id: string): Observable<UserEntity> {
    return this.httpClient.get<UserEntity>(`${this.urlBase}/${id}`);
  }
}

The problem is that apiUserData gets into a loop of calls instead of asking only once. userData works fine, but it returns data from the service without http. Why does this happen?

Share Improve this question edited Mar 27 at 20:16 jonrsharpe 122k30 gold badges268 silver badges476 bronze badges asked Mar 19 at 17:26 TalVik99TalVik99 1981 silver badge13 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Since it is angular 19, use rxResource (Directly use the service method which returns an observable) or httpResource (Directly use the url to get the data) to achieve this.

We use toSignal to convert the observable from oidc to a signal.

@Component({
  selector: 'app-profile',
  template: `
    @let userData = userData();
    @let apiUserData = apiUserDataRx.value();
    @let apiUserData2 = apiUserDataHttp.value();
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProfileComponent {
  readonly userData = toSignal(oidcService.getUserData());
  public readonly oidcService = inject(OidcSecurityService);
  public readonly usersService = inject(UsersService);
  
  apiUserDataRx = rxResource({
    request: () => this.userData(),
    loader: ({ request: userData }) => this.usersService.usersGet(userData.sub),
  });
  
  apiUserDataHttp = httpResource(() => `${this.urlBase}/${this.userData().sub}`);
}
发布评论

评论列表(0)

  1. 暂无评论