Я бы предложил подумать о SOLID и разделить обязанности.
User
- это объект со свойствами name
и img
. Он не должен знать о DBService
.
. Вы можете создать фабрику для создания User
экземпляров. И фабрика узнает о DBService
. Фабрика может работать двумя способами:
- синхронно создавать и возвращать экземпляр
User
, а затем асинхронно заполнять свойство img
, если DbService.getSkin
будет вызываться - создавать и возвращать
User
экземпляр асинхронно через наблюдаемый - всегда.
Я думаю, что случай 2 лучше, потому что он имеет более предсказуемое поведение и не имеет неожиданного обновления свойства img
.
Код будет например:
case1 - вернуть User
экземпляр
interface User {
name: string;
img: ElementRef<HTMLCanvasElement> | string[];
}
@Injectable({providedIn: 'root')
export class UserFactory {
constructor(private dbService: DBService) {}
create(
name: string,
img?: ElementRef<HTMLCanvasElement> | string[],
): User {
const user: User = {
name,
img,
}
if (!img) {
this.dbService.getSkin(name).pipe(
tap(someResponse => {
/*
SET IMG HERE
user.img = someResponse
*/
}),
).subscribe();
}
return user;
}
}
case 2 - вернуть наблюдаемый
interface User {
name: string;
img: ElementRef<HTMLCanvasElement> | string[];
}
@Injectable({providedIn: 'root')
export class UserFactory {
constructor(private dbService: DBService) {}
create(
name: string,
img?: ElementRef<HTMLCanvasElement> | string[],
): Observable<User> {
const user: User = {
name,
img,
}
let user$: Observable<User> = of(user);
if (!img) {
user$ = this.dbService.getSkin(name).pipe(
map(someResponse => {
/*
SET IMG HERE
user.img = someResponse
*/
return user;
}),
)
}
return user$;
}
}
Фабрика отвечает за работу с API в обоих случаях , Это решение имеет более четкую структуру и более тестируемо.