Как включить проанализированный ответ и заголовки исходного ответа в ошибки выборки

У меня есть следующая цепочка обещаний:

return fetch(request)
  .then(checkStatus)
  .then(response => response.json())
  .then(json => ({ response: json }))
  .catch(error => ({ error }))

Где checkstatus() проверяет, был ли запрос успешным, и возвращает ошибку, если это не так. Эта ошибка будет перехвачена и возвращена. Но проблема в том, что я хочу добавить к ошибке как response.statusText, так и результаты response.json(). Проблема в том, что когда я разбираю его, я теряю исходный ответ в цепочке, так как мне нужно вернуть response.json(), потому что это обещание.

Вот что сейчас делает checkstatus:

const checkStatus = response => {
  if (response.ok) return response

  const error = new Error('Response is not ok')

  // this works because the response hasn't been parsed yet
  if (response.statusText) error.message = response.statusText

  // an error response from our api will include errors, but these are
  // not available here since response.json() hasn't been called
  if (response.errors) error.errors = response.errors

  throw error
}

export default checkStatus

Как вернуть ошибку с error.message = response.statusText и error.errors = response.json().errors?


person Community    schedule 06.01.2017    source источник
comment
@Bergi Этот вопрос конкретно о том, как правильно обрабатывать ошибки при выборке, что, возможно, менее тривиально, чем должно быть. Поэтому я думаю, что эта проблема заслуживает отдельного вопроса и не должна быть закрыта как дублирование более общего организационного вопроса.   -  person jib    schedule 08.01.2017
comment
@jib Проблема в том, что когда я анализирую его, я теряю исходный ответ в цепочке, так как мне приходится возвращать response.json(), потому что это обещание — это именно то, о чем канонический вопрос.   -  person Bergi    schedule 08.01.2017
comment
@Bergi Предлагаемое здесь решение отличается и, на мой взгляд, более понятно.   -  person    schedule 09.01.2017


Ответы (2)


Вот мой помощник для разумной обработки ошибок fetch, fetchOk:

let fetchOk = (...args) => fetch(...args)
  .then(res => res.ok ? res : res.json().then(data => {
    throw Object.assign(new Error(data.error_message), {name: res.statusText});
  }));

Который я затем заменяю на выборку.

let fetchOk = (...args) => fetch(...args)
  .then(res => res.ok ? res : res.json().then(data => {
    throw Object.assign(new Error(data.error_message), {name: res.statusText});
  }));

fetchOk("https://api.stackexchange.com/2.2/blah")
  .then(response => response.json())
  .catch(e => console.log(e)); // Bad Request: no method found with this name

var console = { log: msg => div.innerHTML += msg + "<br>" };
<div id="div"></div>

Он не загружает данные, если нет ошибки, что делает его прямой заменой.

person jib    schedule 07.01.2017

Я использую новый синтаксис async/await, так как он читается более интуитивно:

 async fetchData(request) {
    try {
      const response = await fetch(request)
      const data = await response.json()

      // return the data if the response was ok
      if (response.ok) return { data }

      // otherwise return an error with the error data
      const error = new Error(response.statusText)
      if (data.errors) error.errors = data.errors

      throw error
    } catch (error) {
      return { error }
    }
  }

Это позволяет очень легко обрабатывать как обещание, которое возвращает fetch, так и обещание, которое возвращает response.json().

person Community    schedule 06.01.2017