각도 부하 표시

18558 단어 uxangularrxjswebdev
2019년 1월 30일 기준nils-mehlhorn.de
이것은 흔히 볼 수 있는 소망이다. 일부 물건을 회전시키거나 비행시켜 사용자를 즐겁게 하고, 성능이 적당한 백엔드는 하느님이 아시는 곳에서 데이터를 얻게 하는 것이다.서버가 왕복할 때 대여 spinner from CodePen 가 쉬울 것 같지만, 우리는 흔히 볼 수 있는 오해와 함정을 규명할 것이다.

데이터 대기 중


일반적인 작업부터 시작합시다. 서비스를 통해 비동기적으로 얻은 사용자 목록을 표시하고 싶습니다.경험이 없으면서도 기술적으로 좋은 솔루션은 다음과 같다.
export class UserComponent implements OnInit  {

  users: User[]
  loading = false

  constructor(private userService: UserService) {}

  ngOnInit(): void {
    this.loading = true
    this.userService.getAll().pipe(
      finalize(() => this.loading = false)
    ).subscribe(users => this.users = users)
  }
}
실례 변수는 사용자를 저장하는 데 사용되고, 다른 변수는 사용자가 아직 불러오거나 도착했는지 표시하는 데 사용됩니다.구독 (이동 호출을 촉발하기 전에) 마운트 로고가 업데이트됩니다.호출이 완료되면 finalize 연산자를 사용하여 재설정합니다.이 연산자에게 전달되는 리셋은 호출이 끝난 후에 호출됩니다. 결과가 어떻든지 간에.만약 이것이 구독 리셋 내에서만 완성된다면, 불러오는 로고는 성공적으로 호출된 후에만 리셋되며, 오류가 발생할 때 리셋되지 않습니다.해당 뷰는 다음과 같습니다.
<ul *ngIf="!loading">
  <li *ngFor="let user of users">
    {{ user.name }}
  </li>
</ul>
<loading-indicator *ngIf="loading"></loading-indicator>
그러나 대부분의 제공 데이터가 보기에 직접 표시되는 호출에 대해서는 AsyncPipe 을 사용하여 이 설정을 간소화할 수 있습니다.구성 요소는 다음과 같이 단축됩니다.
export class UserComponent implements OnInit  {

  users$: Observable<User[]>

  constructor(private userService: UserService) {}

  ngOnInit(): void {
    this.users$ = this.userService.getAll()
  }
}
현재, 이 구성 요소는 사용자 흐름을 보기에 직접 공개합니다.보기를 업데이트하려면 async as 구문을 사용합니다.
일단 흐르면 그 값을 단독users 변수에 연결합니다.
<ul *ngIf="users$ | async as users; else indicator">
  <li *ngFor="let user of users">
    {{ user.name }}
  </li>
</ul>
<ng-template #indicator>
  <loading-indicator></loading-indicator>
</ng-template>
else*ngIf 블록에 보기 템플릿을 제공함으로써 마운트 로고를 현저하게 관리할 필요가 없습니다.이 방법은 두 개의 단독 if 블록이 아닌 if-else 연결을 통해 두 개의 보기 상태를 연결하기 때문에 더욱 성명성이 있다.이 밖에 우리는 더 이상 흐르는 구독을 관리할 필요가 없다. 왜냐하면 이것은 파이프에서 완성된 것이기 때문이다. (구성 요소가 파괴되었을 때 구독을 취소하는 것을 포함한다.)

작업 대기 중


우리가 단추를 눌러 새 사용자를 만드는 것과 같은 작업을 처리할 때, AsyncPipe는 우리를 실망시켰다.관찰할 수 있는 정보를 보기로 전송할 수 없을 때, 구성 요소 내부에서 구독해야 합니다.
우선, 어떤 사람들은 동의하지 않을 수도 있지만, 나는 이번 로고 사용 방법이 효과적이라고 생각한다.잘못된 예언가를 따르지 말고 가장 가벼운 쓸데없는 것을 비난해라.가능한 한 적은 줄로 끝내지 말고 코드를 쉽게 이해하고 테스트하며 delete 해야 할 때가 많다.그래서 이렇게 하면 좋다.
<button (click)="create()">Create User</button>
<div *ngIf="loading">
  Creating, please wait <loading-indicator></loading-indicator>
</div>
export class UserComponent  {

  loading: boolean

  constructor(private userService: UserService) {}

  create(name = "John Doe"): void {
    this.loading = true
    this.userService.create(new User(name)).pipe(
      finalize(() => this.loading = false)
    ).subscribe()
  }
}
이제 이 두 줄이 모든 구성 요소에서 마운트 표시를 현저하게 전환하는 것을 단호히 반대한다면 우리가 무엇을 할 수 있는지 봅시다.

차단기 접근


나는 어떤 사람이 현재 어떤 통화를 처리하고 있는지 관찰하기 위해 HttpInterceptor 를 사용하라고 건의하는 것을 보았다.이러한 차단기는 이 선을 따라 볼 수 있다.
@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
  constructor(private loadingService: LoadingService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // you could also check for certain http methods here
    this.loadingService.attach(req);
    return next.handle(req).pipe(
      finalize(() => this.loadingService.detach(req)),
    );
  }
}
이를 통해viaattach(req)의 요청이 시작되면 단독 로드 서비스를 알려 줍니다.요청이 완료되면 detach(req) 서비스를 통해 다시 알려 드립니다.이 서비스는 호출할 때마다 열려 있는 요청이 있는지 확인하여 전역 로드 로고를 관리할 수 있습니다.
나 자신도 이런 방법을 사용한 적이 있다. 심지어는 AngularJS에서도.
나는 이것이 사용자에게 응용 프로그램의 불러오는 시간을 제공하는 일반적인 지시라고 생각하지만, 너는 확실히 해냈다
세 가지를 고려해야 한다.
1) 당신은 전일성을 잃었습니다.모든 요청은 로딩 로고가 아니라 전역 로고이기 때문에 어떤 요청이 대기 시간인지 알 수 없습니다.모든 구성 요소에 서비스를 주입하고 로컬 지시를 표시할 수 있지만, 진정한 정보는 전 세계 응용 프로그램 수준에 있습니다.단일 요청의 지시자로 사용하는 것은 의미에서 잘못된 것입니다.
2) 사용자는 글로벌 로드 지시를 어떻게 처리할 계획입니까?응용 프로그램의 모든 내용이 불러오기만 하면 모든 내용을 비활성화할 수 있습니까?사용자는 전체 지시가 끝날 때까지 기다려야 합니까?사용자의 현재 작업과 무관한 요청이 걸리면 어떻게 합니까?
3) 너희들의 결합은 매우 이상하다.HTTP 호출을 서비스 뒤에 숨기고 보기 논리와 조심스럽게 분리하기 위해 최선을 다했습니다. 그러면 이제 스스로 숨길 수 있습니다.나는 그것을 완전히 비난하지 않을 것이다. 단지 생각해 볼 뿐이다.

뭐 공부 해요?


차단기 방법에 만족하면 응용 프로그램 창의 왼쪽 상단에서 오른쪽 상단까지의 진행 표시줄과 같은 전역 지시에 사용할 수 있습니다. 다음 그림과 같습니다.

글로벌 로드 지시
일부 주류 응용 프로그램들이 이렇게 하고 있는데, 그것은 보기에 좀 화려하고, 이미 일부 교과서와 떳떳한 도서관들이 그곳에서 이러한 행위를 충분히 배려하고 있다.
그럼에도 불구하고, 만약 우리가 사용자에게 도대체 무엇이 그의 시간을 낭비하고 있는지, 심지어는 일부 상호작용을 동시에 사용하지 않는지 알려주고 싶다면, 우리는 반드시 다른 방법을 생각해 내야 한다.

컨텍스트 로드 지시
양자의 차이를 이해하는 것은 매우 중요하다.그렇지 않으면, 페이지의 다른 곳에서 호출된 것 (예를 들어 삽화의 맨 오른쪽 작은 위젯) 이 진정한 원흉이지만, 양식 작업 (예를 들어 삽화의 왼쪽 아래) 이 여전히 불러오고 있음을 지적할 수 있습니다.
단순성에 우롱당하지 말고, 반대로 당신이 무엇을 원하는지 알아야 그것을 어떻게 구축할 수 있는지 생각해 낼 수 있다.

반응어경법


로드 플래그를 명시적으로 뒤집지 않고 특정 컨텍스트 로드 지시를 수행하려면 RxJS 연산자를 사용할 수 있습니다.RxJS 6 때문에 순수 함수 형식으로 연산자를 정의할 수 있습니다.우선, 구독할 때 리셋을 호출하는 조작부호가 있습니다.이것은 RxJS 방법defer을 사용하여 수행할 수 있습니다.
export function prepare<T>(callback: () => void): (source: Observable<T>) => Observable<T> {
  return (source: Observable<T>): Observable<T> => defer(() => {
    callback();
    return source;
  });
}
현재, 우리는 마운트 상태의 수신기로 주제를 받아들이는 다른 조작부호를 만듭니다.새로 만든 prepare 연산자를 사용하면 indicator.next(true) 을 통해 실제 원본을 구독할 때 이 테마를 업데이트합니다.이와 유사하게 우리는 finalize 연산자를 사용하여 indicator.next(false) 연산자를 통해 완료된 로드를 알립니다.
export function indicate<T>(indicator: Subject<boolean>): (source: Observable<T>) => Observable<T> {
  return (source: Observable<T>): Observable<T> => source.pipe(
    prepare(() => indicator.next(true)),
    finalize(() => indicator.next(false))
  )
}
그러면 다음과 같이 어셈블리에서 새 indicate 연산자를 사용할 수 있습니다.
export class UserComponent  {
  loading$ = new Subject<boolean>()

  constructor(private userService: UserService) {}

  create(name = "John Doe"): void {
    this.userService.create(new User(name))
    .pipe(indicate(this.loading$))
    .subscribe()
  }
}
<button (click)="create()">Create User</button>
<div *ngIf="loading$ | async">
  Creating, please wait <loading-indicator></loading-indicator>
</div>
나는 이미 이 부분들을 StackBlitz의 완전한 예시에 놓았다.첫 번째 표시기를 보려면 다시 로드한 다음 사용자 만들기를 클릭하여 두 번째 표시기를 봅니다.그리고 StackBlitz의 파란색 지시기에 신경 쓰지 마세요. 저희는 빨간색입니다.

좋은 웹페이지 즐겨찾기