onreadystatechange / blogs

主要记录项目中的重难点,以及如何攻克,有一定的借鉴意义,主要写在Issues
3 stars 0 forks source link

公用fetch封装实现,可在fetch中判断状态码,执行副作用 #1

Open onreadystatechange opened 5 years ago

onreadystatechange commented 5 years ago

fetch封装

onreadystatechange commented 5 years ago
import fetch from 'cross-fetch';
import qs from 'qs';
import { startSignOut, setMessage } from 'store/actions';
import { fromJS } from 'immutable';
export default function(url, options) {
  //默认传cookie
  const defaultOptions = {
    credentials: 'include'
  };
  //删除headers 在下方重置
  delete options.headers;
  let requestUrl = url;
  const newOptions = {
    ...defaultOptions,
    ...options,
    headers: {
      'Access-Control-Allow-Origin': '*',
      Accept: 'application/json',
      'content-type': 'application/json; charset=utf-8'
    }
  };
  newOptions.method = newOptions.method
    ? newOptions.method.toUpperCase()
    : 'GET';
  if (
    newOptions.method === 'POST' ||
    newOptions.method === 'PUT' ||
    newOptions.method === 'DELETE'
  ) {
    if (!(newOptions.body instanceof FormData)) {
      newOptions.headers = {
        ...newOptions.headers,
        Accept: 'application/json',
        'content-type': 'application/json; charset=utf-8'
      };
      newOptions.body = JSON.stringify(newOptions.body);
    } else {
      // newOptions.body is FormData
      newOptions.headers = {
        ...newOptions.headers,
        Accept: 'application/json',
        'content-type': 'multipart/form-data'
      };
    }
  } else {
    const query = qs.stringify(newOptions.body);
    if (query) {
      requestUrl = `${url}?${query}`;
    }
    newOptions.body = undefined;
  }

  return fetch(requestUrl, newOptions)
    .then(checkStatus)
    .then(response => {
      return response.json();
    })
    .then(response => {
      if (response && response.code && response.code !== 0) {
        const { dispatch } = window.starc.store;
        dispatch(
          window.starc.apps.auth.actions.setMessage({
            action: 'error',
            content:
              window.starc.errorMessages[response.message] ||
              `未知错误:${response.code}`,
            duration: 3
          })
        );
        throw {
          HTTP_CODE: 400,
          ...response
        };
      }
      return response;
    })
    .catch(e => {
      console.log('fetchError:', e);
      throw e;
    });
}

function checkStatus(response) {
  if (
    (response.status >= 200 && response.status < 300) ||
    response.status === 400
  ) {
    return response;
  } else if (response.status === 401) {
    const { dispatch } = window.starc.store;
    //重置store
    window.starc.apps.ta &&
      dispatch(
        window.starc.apps.ta.actions.setTa(window.starc.apps.ta.defaultStore.ta)
      );
    dispatch(startSignOut());
    dispatch(
      window.starc.apps.auth.actions.setMessage({
        action: 'warning',
        content: '请重新登陆',
        duration: 3
      })
    );
    throw {
      message: '账号已失效,请重新登陆'
    };
  } else if (response.status === 403) {
    const { dispatch } = window.starc.store;
    dispatch(
      window.starc.apps.auth.actions.setMessage({
        action: 'warning',
        content: '此用户暂无权限查看',
        duration: 3
      })
    );
    throw {
      message: '无权限'
    };
  }
}
onreadystatechange commented 5 years ago

结合redux-sga使用

import { call, put } from 'redux-saga/effects';
import apiBase from 'src/apiBase';

import { setTag } from 'store/actions';

export function* addTag(name) {
  const fetchPayload = {
    method: 'post',
    headers: {
      'content-type': 'application/json'
    },
    credentials: 'include',
    body: {
      name: name
    }
  };
  try {
    const resource = yield call(window.starc.fetch, `${apiBase.apiTaUrl}/api-v2/ta_node/tag`, fetchPayload);
    if (resource.success) {
      yield put(setTag({ id: resource.data.id, name: resource.data.name }));
    }
  } catch (e) {
    console.log(e);
  }
}