как анализировать json после обещания обработки исключений с помощью isomorphic-fetch

Во время реализации функции входа в систему с помощью React, Redux, isomorphic-fetch, ES6 Babel.

Вопросы

Я не знаю, как правильно комбинировать промисы после промиса checkstatus, чтобы получить проанализированные данные JSON с моего сервера.
что я здесь делаю неправильно?

также, нужно ли заменить isomorphic-fetch пакет на другой, более удобный?
любые предложения по другому пакету приветствуются!

loginAction.js

import * as API from '../middleware/api';
import * as ActionTypes from '../actionTypes/authActionTypes';
import 'isomorphic-fetch';

function encodeCredentials(id, pwd) {
  return btoa(`${id}{GS}${pwd}`);
}

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    response;
  } else {
    const error = new Error(response.statusText);
    error.response = response;
    throw error;
  }
}

function parseJSON(response) {
  return response.json();
}

export function loginFailure(error) {
  return { error, type: ActionTypes.LOGIN_FAILURE };
}

export function loginSuccess(response) {
  return dispatch => {
    dispatch({ response, type: ActionTypes.LOGIN_SUCCESS });
  };
}

export function loginRequest(id, pwd) {
  return {
    type: ActionTypes.LOGIN_REQUEST,
    command: 'login',
    lang: 'en',
    str: encodeCredentials(id, pwd),
    ip: '',
    device_id: '',
    install_ver: '',
  };
}


export function login(id, pwd) {
  const credentials = loginRequest(id, pwd);

  return dispatch => {
    fetch(`${API.ROOT_PATH}${API.END_POINT.LOGIN}`, {
      method: 'post',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(credentials),
    })
    .then(checkStatus)
    .then(parseJSON)
    .then(data => {
      console.log(`parsed data ${data}`);
      dispatch(loginSuccess(data));
    })
    .catch(error => {
      console.log(`request failed ${error}`);
    });
  };

}

person seoyoochan    schedule 13.01.2016    source источник


Ответы (2)


В моих проектах обычно есть вспомогательная функция fetchJSON, которая выполняет всю служебную логику, например анализ JSON и проверку состояния.

Вот:

import fetch from 'isomorphic-fetch';

function checkStatus(response) {
  if(response.ok) {
    return response;
  } else {
    const error = new Error(response.statusText);
    error.response = response;
    throw error;
  }
}

function parseJSON(response) {
  return response.json();
}

export default function enhancedFetch(url, options) {
  options.headers = Object.assign({
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  }, options.headers);
  if(typeof options.body !== 'string') {
    options.body = JSON.stringify(options.body);
  }
  return fetch(url, options)
    .then(checkStatus)
    .then(parseJSON);
}

Затем вы можете использовать его в действиях:

import fetchJSON from '../utils/fetchJSON'; // this is the enhanced method from utilities

export function login(id, pwd) {
    const credentials = loginRequest(id, pwd);

    return dispatch => {
       fetchJSON(`${API.ROOT_PATH}${API.END_POINT.LOGIN}`, {
           method: 'post',
           body: credentials
       }).then(data => {
           console.log(`parsed data ${data}`);
           dispatch(loginSuccess(data));
       }).catch(error => {
           console.log(`request failed ${error}`);
       });
   };
}

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

person just-boris    schedule 14.01.2016
comment
Ух ты! Я правда ценю это. Это действительно полезные лучшие практики, которые я когда-либо видел! - person seoyoochan; 14.01.2016
comment
Назначение объекта, изменяющее исходный объект, выдает предупреждение, поэтому я передал {} в качестве первого аргумента. - person seoyoochan; 14.01.2016
comment
Я вижу, что при ошибке вы устанавливаете error.response = response Что делать, если сервер API отправляет объект Error в соответствии со спецификацией JSON API? jsonapi.org/format/#error-objects Как бы вы тогда проанализировали объект ошибки? - person bhtabor; 06.06.2016
comment
@Biruk вы можете найти решение в соответствующем вопросе: stackoverflow.com/questions/29473426/ - person just-boris; 07.06.2016
comment
@Biruk также, если вам приходится иметь дело с JSON API обычным способом, вы можете использовать для него специальную библиотеку, например github.com/mzabrskie/axios - person just-boris; 07.06.2016
comment
@just-boris Я использую isomorphic-fetch, но связанный с этим вопрос очень полезен. Большое спасибо! - person bhtabor; 09.06.2016
comment
Хороший фрагмент кода. Всего один комментарий: Object.assign не поддерживается в IE, так что этот код сломается для пользователей Windows. Вместо этого используйте некоторый полифилл, чтобы сделать копию без использования Object.assign, как это developer.mozilla.org/en/docs/Web/JavaScript/Reference/ - person sandino; 07.01.2017

Вы все делаете правильно, вы просто забыли return в checkstatus; вы должны вернуть response таким образом, чтобы следующее обещание в цепочке могло его использовать.

Кроме того, кажется, что checkstatus является синхронной операцией, поэтому не нужно связывать ее с .then (хотя это нормально, если вам так нравится), вы можете написать:

fetch(...)
.then(response=>{
   checkStatus(response)
   return response.json()
})
.then(data=>{
   dispatch(loginSuccess(data))
})
.catch(...)

Не вижу смысла пока избавляться от isomorphic-fetch - вроде свое дело делает.

person Tomas Kulich    schedule 13.01.2016
comment
Нет, response.json() — это асинхронная операция. developer.mozilla.org/en-US/docs/Web/ API/тело/json - person just-boris; 14.01.2016
comment
Спасибо за ваш ответ - person seoyoochan; 14.01.2016