Вызов then () дважды по одному и тому же обещанию - PullRequest
0 голосов
/ 26 апреля 2018

Я хочу создать центральный обработчик ajax для всех моих запросов внутри моего приложения React. Это не имеет ничего общего с Redux или чем-то подобным. Это просто «центральный узел» для выполнения ajax-запросов от компонентов React.

Дело в том, что я хочу иметь возможность перехватывать определенные ошибки, чтобы не повторять их при каждом вызове ajax. В конце концов, я хочу снова вызвать then () из компонента, который фактически инициировал запрос

Вот что я сделал:

import axios from 'axios';
import handleError from './error';

export default (endPoint, method = 'get', data) => {

return axios({
    url: window.BASE_API + endPoint,
    method,
    data
}).then(({ data }) => {
    if (data.status !== 'ok') {
        handleError(data.errorMessage);
    }
}).catch((error) => {
    handleError(error);
})

}

В компоненте реакции:

import ajax from '../../services/ajax';

componentDidMount() {
ajax('/content')
  .then(({ data }) => {
    this.setState(() => ({ pages: data.content }))
  })
 }

Это приводит к ошибке: Uncaught (в обещании) TypeError: Невозможно прочитать свойство 'data' из неопределенного

Как я могу выполнить обещание дважды?

РЕДАКТИРОВАТЬ: так выглядит мой объект ответа:

 {content: Array(18), status: "ok", errorMessage: null, metaData: null}

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Обновлено, чтобы избавиться от явного обещания конструкции antipattern. Спасибо Roamer!

В этом случае было бы хорошо, если бы ваш вызов API сам возвращал обещание. Как то так:

const apiCall = (params) => axios(params).then({ data } => { // Note here that you are extracting the property "data" from whatever the axios call returns.
  if (data.status !== 'ok') {
    throw new Error(data.errorMessage) // Rejects the promise
  } else {
    return data // Resolve the data
  }
)}

Тогда вы бы использовали это так:

apiCall(params)
   // Since you resolved the raw data, no need to use object extraction unless the property you're trying to get out is `data.data`
  .then(data => this.setState({pages: data.content}))
  .catch(e => handleError(e))

Вот как вы могли бы эффективно сделать пользовательское обещание, которое обрабатывает все случаи ошибок, о которых вы говорите. Может произойти пара вещей, но я думаю, что одна из них может заключаться в том, что вы сначала извлекаете {data} из ответа axios, а затем используете результат обещания без разрешения новых данных. Затем при вызове .then() вы снова извлекаете {data} (и, как говорится в ошибке, она не определена). Если вы заключите весь вызов в новое обещание, вы можете справиться с ним (я думаю) именно так, как вы хотите.

0 голосов
/ 26 апреля 2018

Попробуйте это:

  return axios({
    url: window.BASE_API + endPoint,
    method,
    data
   }).then(({ data }) => {
     if (data.status !== "ok") {
        handleError(data.errorMessage);
     } else {
        return Promise.resolve(data);
     }
  }).catch((error) => {
  handleError(error);
 })
 }

Вы также должны изменить это:

componentDidMount() {
 ajax('/content')
   .then(({ content }) => {
   this.setState(() => ({ pages: content }))
 })
}
...