Маршрутизатор выполняет немедленное выполнение в методе async / await - PullRequest
0 голосов
/ 24 февраля 2020

У меня есть компонент A , который имеет asyn c метод ab c () . Внутри этого метода я жду другого asyn c метода xyz () внутри службы X . В этом методе xyz () у меня есть еще ожидающие вызовы (мне нужно выполнить вызовы по порядку и использовать ответ в следующем запросе). Может случиться так, что в случае отрицательных результатов при двух указанных c вызовах, я бы хотел перенаправить пользователя на одну из двух страниц (в настоящее время давайте предположим, что это только одна страница). Я использую router.navigate(['/error']), но он не работает, как я ожидал ... Я ожидаю, что он остановит дальнейшее выполнение кода и выполнит немедленное перенаправление.

x.service.ts

async ngOnInit() {
   await this.abc();
}

async abc(): Promise<any> {
   await this.serviceX.xyz();

   // below calls are still executed even if we entered the navigation line in xyz() method
   await this.service3.magicMethod();
   await this.service4.anotherMethod();
}

a.component.ts

async xyz(): Promise<any> {
   const result = await this.service1.getData(); // 
   if (result !== 'OK') {
      this.router.navigate(['/error']);
   }

   const userAnswer = await this.service2.userSelection();
   if (userAnswer !== 'OK') {
      this.router.navigate(['/error']);
   }
}

И service1, и service2 имеют функции asyn c, где я ожидаю HTTP ответ с использованием toPromise(). Примерно так:

async getData(): Promise<SomeResponse> { // or userSelection()
   const response = await this.wrapperService.getHttpResponse().toPromise();
   console.log(response);
   return response as SomeResponse;
}

1 Ответ

1 голос
/ 24 февраля 2020

Если вы ожидаете, что обработка прекратится, вам нужно сказать, чтобы она прекратилась. Вызванная функция router.navigate будет продолжать обрабатываться, если не указано иное.

В вашем случае похоже, что вы выполняете маршрутизацию в службе, из-за которой возникают проблемы с пользовательским интерфейсом на уровне службы. Я бы реорганизовал ваш метод обслуживания, чтобы вернуть результат, указывающий на успех или неудачу. Ваш компонент может затем выбрать навигацию или продолжить обработку.

service.ts

async xyz(): Promise<boolean> {
   const result = await this.service1.getData(); // 
   if (result !== 'OK') {
       // no further processing
      return false;
   }

   const userAnswer = await this.service2.userSelection();
   if (userAnswer !== 'OK') {
      // no further processing
      return false;
   }

   return true;
}

component.ts

async ngOnInit() {
   await this.abc();
}

async abc(): Promise<any> {
   const success = await this.serviceX.xyz();
   if (!success) {
     this.router.navigate(['/error']);
     // no further processing
     return;
   }

   await this.service3.magicMethod();
   await this.service4.anotherMethod();
}

Я добавил return; операторов после вашего звонка на router.navigate, чтобы прекратить дальнейшую обработку.

Если вам нужно вернуть больше информации, которая имеет значение true / false, из вашей службы, то вы можете вернуть либо ошибку сообщение или какой-то объект. Хотя для объяснения концепции достаточно логического значения.

РЕДАКТИРОВАТЬ:

Очевидно, что если вы действительно хотели выполнить маршрутизацию в службе, ничто не помешает вам сделать это там , Вы все равно будете следовать этой схеме возврата результата успеха, за исключением того, что навигация теперь происходит в службе перед каждым оператором return false;.

РЕДАКТИРОВАТЬ 2:

Как мы обсуждали в комментариях, я Я не пытаюсь здесь продиктовать ваше решение по проектированию, а просто предлагаю образец того, как вы можете решить вашу проблему.

Существует больше накладных расходов при возврате результата ошибки и последующем сопоставлении этого результата с путем, но я бы хотел все же лично для ясности предпочитаю это, чем смешивать маршрутизацию с вызовами данных На ум приходит фраза спагетти-кода ...

Пример такого подхода, который я бы использовал для разделения вызовов службы и маршрутизации. Это просто демонстрация шаблона, а не готового кода, но, надеюсь, даст вам некоторые идеи. Я не против немного больше печатать в обмен на более чистый дизайн.

service.ts

export enum XyzError = { ErrorA = 1, ErrorB = 2 }

async xyz(): Promise<XyzReason> {
   const result = await this.service1.getData(); // 
   if (result !== 'OK') {
       return XyzReason.ErrorA;
   }

   const userAnswer = await this.service2.userSelection();
   if (userAnswer !== 'OK') {
      return XyzReason.ErrorB;
   }

   return null;
}

component.ts

async abc(): Promise<any> {
   const result: XyzReason = await this.serviceX.xyz();
   switch (result)  {
     case XyzReason.ErrorA:
       this.router.navigateByUrl('/errora');
       return;
     case XyzReason.ErrorB:
       this.router.navigateByUrl('/errorb');
       return;
   }

   await this.service3.magicMethod();
   await this.service4.anotherMethod();
}
...