网络请求

React Native提供了和web标准一致的Fetch API,用于满足开发者访问网络的需求 React Native中已经内置了XMLHttpRequest API(也就是俗称的ajax)。一些基于XMLHttpRequest封装的第三方库也可以使用,例如frisbee或是axios等。

Request 基于fetch 的 Promise 流程:

请求发起 -> 网络判断 -> 超时处理 -> 响应状态判断 -> Promise result

网络判断:

  const isBadNetwork = await NetInfo.getConnectionInfo().then(({ type }) => {
    if (type === 'none' || type === 'unknown') {
      return true;
    } else {
      return false;
    }
  });

超时处理: Promise.race + setTimeout

  const timeoutFetch = (api, options) => {
  const fetchPromise = fetch(HOST + api, options);
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new Error(CODE_MESSAGE.timeOut)), TIMEOUT);
  });
  return Promise.race([fetchPromise, timeoutPromise]);
};

响应状态判断: status >= 200 && res.status < 300

const checkHttpStatus = (res) => {
  if (res.status >= 200 && res.status < 300) {
    return res;
  }
  throw new Error(CODE_MESSAGE.http[res.status] || res.statusText);
};

异步结果:

  return Promise.resolve(result);
import NetInfo from "@react-native-community/netinfo";
import Toast from 'react-native-root-toast';

import { HOST } from '~/contants/Config';
import { CODE_MESSAGE } from '~/contants/Common';

const TIMEOUT = 20 * 1000;

// 对象转请求字符串 id=2&name='xxx'
const stringParams = obj =>
  Object.keys(obj)
    .reduce((acc, cur) => acc.concat([[cur, obj[cur]].join('=')]), [])
    .join('&');

const GET = (api, params = {}) => {
  const options = {
    method: 'GET',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
  };
  const str = stringParams(params);
  const url = str.length > 0 ? `${api}?${str}` : api;
  return request(url, options);
};

const POST = (api, params = {}) => {
  const options = {
    method: 'POST',
    body: JSON.stringify(params),
    headers: {
      'Content-Type': 'application/json;charset=UTF-8',

    },
  };
  return request(api, options);
};

// 提示
const toastHandler = msg => Toast.show(msg, { position: Toast.positions.CENTER });

// 响应状态判断
const checkHttpStatus = (res) => {
  if (res.status >= 200 && res.status < 300) {
    return res;
  }
  throw new Error(CODE_MESSAGE.http[res.status] || res.statusText);
};

// 超时
const timeoutFetch = (api, options) => {
  const fetchPromise = fetch(HOST + api, options);
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new Error(CODE_MESSAGE.timeOut)), TIMEOUT);
  });
  return Promise.race([fetchPromise, timeoutPromise]);
};

const request = async (api, options) => {
  const isBadNetwork = await NetInfo.getConnectionInfo().then(({ type }) => {
    if (type === 'none' || type === 'unknown') {
      return true;
    } else {
      return false;
    }
  });

  if (isBadNetwork) {
    toastHandler(CODE_MESSAGE.networkError);
  } else {
    const result = await timeoutFetch(api, options)
      .then(res => checkHttpStatus(res, api, options))
      .then(res => res.json())
      .catch(err => {
        toastHandler(err.message);
        // console.error('request failed: ', err.message, api, options);
      });
    if (result) {
      const { code, msg } = result;

      if (code !== 200) {
        toastHandler(msg);
        return Promise.reject(result);
      }
      return Promise.resolve(result);
    }
  }
};

export default {
  GET,
  POST
}

results matching ""

    No results matching ""