If I were to create an angular2+ component that fetches data from an API and displays its name, which approach would be considered more idiomatic?
Initial Strategy: Using thing
as an object
In this scenario, the component subscribes to a websocket observable and updates its own thing
object accordingly. If child components are utilized, a Thing
will be passed as an input.
interface Thing { name: string }
@Component({
selector: 'app-thing',
template: '<h1> {{ thing?.name }} </h1>',
})
export class ThingComponent implements OnInit {
public thing: Thing
constructor(
private route: ActivatedRoute,
private thingService: ThingService,
) {}
public ngOnInit() {
this.route.params.subscribe(params => {
this.thingService.get(params.id).subscribe(({thing}) => {
this.thing = thing
})
})
this.thingService.socketObservable().subscribe(newThing => {
console.log('Thing has been updated !')
this.thing = newThing
})
}
}
Alternative Approach: Treating thing
as a Subject
This time, instead of using an object like thing: Thing
, we opt for thing: Subject<Thing>
. The template now employs the async
pipe, providing child components with an observable rather than a direct Thing
object.
interface Thing { name: string }
@Component({
selector: 'app-thing',
template: '<h1> {{ (thing | async)?.name }} </h1>',
})
export class ThingComponent implements OnInit {
public thing: Subject<Thing>
constructor(
private route: ActivatedRoute,
private thingService: ThingService,
) {}
public ngOnInit() {
this.thing = new Subject<Thing>()
this.route.params.subscribe(params => {
this.thingService.get(params.id).subscribe(({thing}) => {
this.thing.next(thing)
})
})
this.thingService.socketObservable().subscribe(newThing => {
console.log('Thing has been updated !')
this.thing.next(newThing)
})
}
}
Both versions appear functional on the surface. However, it's unclear whether they are equivalent beneath the surface. Any thoughts on whether the first or second approach is preferable?