Обработка ошибок для fetch() в Aurelia

У меня есть API, который содержит полезное описание того, что пошло не так, когда ошибка возникает сервером (статус = 500). Описание является частью текста ответа. Мой клиентский код, используя Aurelia, вызывает api через aurelia-fetch-client с помощью общего метода для вызова:

function callRemoteService(apiName, timeout) {
  return Promise.race([
    this.http.fetch(apiName),
    this.waitForServer(timeout || 5000)  // throws after x ms
  ])
    .then(response => response.json() )
    .catch(err => {
        if (err instanceof Response) {
          // HERE THE PROBLEM.....
          err.text().then(text => {
            console.log('Error text from callRemoteService() error handler: ' + text);
            throw new Error(text)
          });
        } else if (err instanceof Error) {
          throw new Error(err.message);
        } else {
          throw new Error('Unknown error encountered from callRemoteService()');
        }
    });
}

Обратите внимание, что я хочу последовательно отслеживать ошибки на сервере (выборка или тайм-аут), а затем throw вернуть простое сообщение об ошибке в вызывающий вид. Я могу успешно вызвать callRemoteService, поймав ошибки, когда возвращается 500 с помощью:

callRemoteService(this.apiName, this.apiTimeout)
  .then(data => {
    console.log('Successfully called \'' + this.apiName +
      '\'! Result is:\n' + JSON.stringify(data, null, 2));
    })
  .catch(err => {
    console.log('Error from \'' + this.apiName + '\':',err)
    });

Однако у меня возникают проблемы с доступом к тексту ответа, потому что fetch предоставляет метод text(), который возвращает обещание, и это мешает моей дружеской цепочке обещаний. Вышеприведенный код не работает, оставляя меня с ошибкой Uncaught (in promise).

Надеюсь, есть хороший способ получить доступ к этому тексту ответа?

Ответы

Ответ 1

Это должно сделать трюк:

function callRemoteService(apiName, timeout = 5000) {
  return Promise.race([
    this.http.fetch(apiName)
      .then(
        r => r.json(),
        r => r.text().then(text => throw new Error(text))
      ),
    this.waitForServer(timeout)
  ]);
}

Кстати, мне нравится, что вы делаете с Promise.race - хорошая техника!