Объединение / упрощение двух обещаний, вызываемых в нескольких функциях - PullRequest
0 голосов
/ 14 мая 2018

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

  noteCreate(): Promise<any> {
    return new Promise (resolve => {
      this.connCheck()
      .then(success => {
        if (success) {
          this.authCheck('Please login first!')
          .then(success => {
            if (success) {

              // API CALL

            }
          });
        }
      })
    });
  }

Я надеюсь, что есть способ, которым я мог бы украсить свои вызовы API или сжать эти две проверки во что-то простое и не столь громоздкое / повторяющееся, но яЯ не уверен, как мне поступить об этом.

Я ищу и connCheck, и authCheck, чтобы вернуть true, чтобы продолжить вызовы API.Я хочу сохранить эти функции отдельно, потому что в некоторых случаях мне нужно только проверять соединение, а в других - только аутентификацию (локально).

  connCheck(): Promise<boolean> {
    return new Promise(resolve => {
      this.http.get(this.myURL() + '/heartbeat/', {responseType: 'text'}).subscribe(
        (data) => {
          resolve(true);
        },
        (err) => {
          resolve(false);
        }
      );
    })
  }

  authCheck(message: string): Promise<boolean> {
    return this.storage.get('user').then((data) => {
      if (data) {
        return true;
      } else {
        return false;
      }
    });
  }

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Этот код содержит антипаттерны, которые иногда называют вложенными обещаниями антипаттернами и строительными антипаттернами (близкий родственник отложенного антипаттерна ).

Уже есть обещание, которое может быть приковано цепью. Нет необходимости создавать еще один, new Promise (resolve => ...).

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

Если имеется несколько условий, цепочка обещаний может быть сглажена путем разрыва с отклонением:

  noteCreate(): Promise<any> {
    const alreadyAuthorized = new Error();

    return this.connCheck()
    .then(success => {
      if (success)
        return this.authCheck('Please login first!')
      else
        throw alreadyAuthorized ;
    })
    .then(success => {
       if (success) {
         return ... // API CALL
       }
    ))
    .catch(err => {
      if (err === alreadyAuthorized)
        return;
      else
        throw err;
    });
  }

Более удобный способ - перейти на async..await, поскольку он был введен для обеспечения синтаксического сахара для потока управления обещаниями. Отказ может быть переписан для досрочного возврата из функции:

  async noteCreate(): Promise<any> {
    if (!(await this.connCheck()))
      return;

    if (!(await this.authCheck('Please login first!')))
      return;

    return ... // API CALL        
  }

Использование this.http.get(...).subscribe(...) в сочетании с обещаниями является ошибкой. Наблюдаемые можно легко преобразовать в обещания и обратно:

  connCheck(): Promise<boolean> {
    return this.http.get(this.myURL() + '/heartbeat/', {responseType: 'text'})
    .map(Boolean) // maps data to a boolean
    .toPromise();
  }
0 голосов
/ 14 мая 2018

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

return this.connCheck()
  .then(() => this.authCheck())
  .then(() => {
     ... API call...
  })
  .catch(error => ...)

Улов будет срабатывать, если какое-либо из обещаний будет отклонено.

Вероятно, вы должны поместить этот улов в самый конец цепочки обещаний.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...