如何在使用同构获取的异常处理承诺后解析 json

Posted

技术标签:

【中文标题】如何在使用同构获取的异常处理承诺后解析 json【英文标题】:how to parse json after exception handling promise with isomorphic-fetch 【发布时间】:2016-04-18 18:50:48 【问题描述】:

在使用 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(`$idGS$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`);
    );
  ;


【问题讨论】:

【参考方案1】:

在我的项目中,我通常有一个辅助函数 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 调用的大型项目中,这确实是必不可少的。

【讨论】:

哇哦!我真的很感激。这是迄今为止我见过的非常有用的最佳实践! 对象赋值修改原始对象会发出警告,所以我将 作为第一个参数。 我看到你设置错误时 error.response = response 如果 API 服务器根据 JSON API 规范发送错误对象怎么办? jsonapi.org/format/#error-objects 那么你会如何解析错误对象呢? @Biruk 您可以在相关问题中找到解决方案:***.com/questions/29473426/… @Biruk 还有,如果你必须以典型的方式处理 JSON API,你可以使用特殊的库,例如github.com/mzabriskie/axios【参考方案2】:

你做得对,你只是在checkstatus 中忘记了return;您应该返回 response 以便链中的下一个承诺可以使用它。

另外,checkstatus 好像是同步操作,所以不用.then 链接(不过,如果你喜欢这样也可以),你可以这样写:

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

我认为目前没有理由摆脱 isomorphic-fetch - 它似乎完成了它的工作。

【讨论】:

不,response.json() 是异步操作。 developer.mozilla.org/en-US/docs/Web/API/Body/json

以上是关于如何在使用同构获取的异常处理承诺后解析 json的主要内容,如果未能解决你的问题,请参考以下文章

如何在循环并进行异步承诺调用后获取重新格式化的 json 对象

Java - 异常解析基础

如何在 AngularJS 中捕获/处理后端异常

如何在承诺中返回修改后的结果作为承诺

如何在js里面处理后台传来的json,并显示在页面上

如何从承诺中获取 JSON [重复]