1. 新建一个dva项目。使用antd 或者antd-mobile组件库。
$ npm install dva-cli -g$ dva -v$ dva new dva-quickstart$ npm start
$ npm install antd babel-plugin-import --save或者是$ npm install antd-mobile babel-plugin-import --save
导入方式css
{"entry": "src/index.js","env": {"development": {"extraBabelPlugins": ["dva-hmr","transform-runtime",["import", { "libraryName": "antd-mobile", "style": "css" }]]},"production": {"extraBabelPlugins": ["transform-runtime",["import", { "libraryName": "antd-mobile", "style": "css" }]]}}}
2. 在该项目的src中utils 创建名为request文件夹。
$ cd dva-quickstart$ cd src$ cd utils
新建文件夹名为request,然后在request文件夹下面创建名为helpers的文件夹以及index.js 和 README.md , request.js 如图所示:
在helpers 下建三个js文件 combineURL.js , isAbsoluteURL.js , serialize.js
combineURL.js中 :
// Creates a new URL by combining the specified URLsconst combineURL = (baseUrl, path) => {return `${baseUrl.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`;};export default combineURL;
isAbsoluteURL.js中 :
// A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).// RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed// by any combination of letters, digits, plus, period, or hyphen.// https://www.ietf.org/rfc/rfc3986.txtconst isAbsoluteURL = (url) => /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);export default isAbsoluteURL;
serialize.js中 :
import { isPresent } from 'lib/lang';const encode = (value) => {return encodeURIComponent(value).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']');};// Encode a set of form elements as a string for submission.const serialize = (params) => {const ret = [];Object.keys(params).forEach(key => {const value = params[key];if (isPresent(value)) {ret.push(`${encode(key)}=${encode(value)}`);}});return ret.join('&');};export default serialize;
3. 在utils下创建一个与request同级的lang.js
lang.js 如下:
export const isPresent = (obj) => {return typeof obj !== 'undefined' && obj !== null;};export const isBlank = (obj) => {return typeof obj === 'undefined' || obj === null;};export const isBoolean = (obj) => {return typeof obj === 'boolean';};export const isNumber = (obj) => {return typeof obj === 'number';};export const isString = (obj) => {return typeof obj === 'string';};export const isArray = (obj) => {return Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Array]';};export const isDate = (obj) => {return obj instanceof Date && !isNaN(obj.valueOf());};export const isFunction = (obj) => {return typeof obj === 'function';};export const isJsObject = (obj) => {return obj !== null && (isFunction(obj) || typeof obj === 'object');};export const isPromise = (obj) => {return isPresent(obj) && isFunction(obj.then);};export const isEmpty = (obj) => {if (isBlank(obj)) {return true;}if (obj.length === 0) {return true;}for (const key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) {return false;}}return true;};export const normalizeBlank = (obj) => {return isBlank(obj) ? null : obj;};export const normalizeBool = (obj) => {return isBlank(obj) ? false : obj;};export const stringify = (token) => {if (isString(token)) {return token;}if (isBlank(token)) {return String(token);}const ret = token.toString();const newLineIndex = ret.indexOf('\n');return (newLineIndex === -1) ? ret : ret.substring(0, newLineIndex);};export class PromiseWrapper {// Excutes promises one by one, e.g.// const promise = () => new Promise(...)// const promise2 = () => new Promise(...)// sequentialize([ promise, promise2 ])static sequentialize = promiseFactories => {let chain = Promise.resolve();promiseFactories.forEach(factory => {chain = chain.then(factory);});return chain;}// Promise finally util similar to Q.finally// e.g. finally(promise.then(...))/* eslint-disable consistent-return */static finally = (promise, cb) => promise.then(res => {const otherPromise = cb();if (typeof otherPromise.then === 'function') {return otherPromise.then(() => res);}}, reason => {const otherPromise = cb();if (typeof otherPromise.then === 'function') {return otherPromise.then(() => {throw reason;});}throw reason;})}/* eslint-enable consistent-return */export class StringWrapper {static equals = (s1, s2) => s1 === s2;static contains = (s, substr) => s.indexOf(substr) !== -1;static compare = (a, b) => {if (a < b) {return -1;} else if (a > b) {return 1;}return 0;}}/* eslint-disable max-params */export class DateWrapper {static create(year,month = 1,day = 1,hour = 0,minutes = 0,seconds = 0,milliseconds = 0) {return new Date(year, month - 1, day, hour, minutes, seconds, milliseconds);}static fromISOString(str) {return new Date(str);}static fromMillis(ms) {return new Date(ms);}static toMillis(date) {return date.getTime();}static now() {return Date.now() || new Date();}static toJson(date) {return date.toJSON();}}/* eslint-enable max-params */
4.这个是dva自动生成的request.js 把这个文件换下名字requests.js,它与lang.js同级。
import fetch from 'dva/fetch';function parseJSON(response) {return response.json();}function checkStatus(response) {if (response.status >= 200 && response.status < 300) {return response;}const error = new Error(response.statusText);error.response = response;throw error;}function parseErrorMessage({ data }) {const { status, message } = data;if (status === 'error') {throw new Error(message);}return { data };}export default function request(url, options) {return fetch(url, options).then(checkStatus).then(parseJSON).then(parseErrorMessage).then((data) => ({ data })).catch((err) => ({ err }));}
request.js
import fetch from 'dva/fetch';import { isEmpty } from '../lang';import serialize from './helpers/serialize';import combineURL from './helpers/combineURL';import isAbsoluteURL from './helpers/isAbsoluteURL';import { apiBaseUrl } from '../../config';import { Toast } from 'antd-mobile';const wait = ms => new Promise(resolve => setTimeout(resolve, ms));const timeout = (p, ms = 30 * 1000) =>Promise.race([p,wait(ms).then(() => {const error = new Error(`Connection timed out after ${ms} ms`);error.statusCode = 408;throw error;}),]);// Request factoryfunction request(url, options, method) {const { endpoint, ...rest } = interceptRequest(url, options, method);const xhr = fetch(endpoint, rest).then(interceptResponse);return timeout(xhr, request.defaults.timeout).catch((error) => {// return Promise.reject(error);});}request.defaults = {baseURL: apiBaseUrl,timeout: 10 * 5000,headers: {Accept: 'application/json',},};// Headers factoryconst createHeaders = () => {const headers = {...request.defaults.headers,};// const auth = JSON.parse(localStorage.getItem('auth'+sessionStorage.getItem("hid")));// const token = sessionStorage.getItem('token'); // <Michael> 登录location获取到的token存放l// if (auth) {// // Toast.info(`请稍等: ${token}`, 2);// // Toast.loading('');// headers.Authorization = auth.Token;// } else if (token) {// // <Michael>;// // Toast.info(`请稍等: ${token}`, 2);// // Toast.loading('');// headers.Authorization = token;// }headers.Authorization = "app";return headers;};// Request interceptorfunction interceptRequest(url, options, method) {let endpoint;if (isAbsoluteURL(url)) {endpoint = url;} else {endpoint = combineURL(request.defaults.baseURL, url);}let data = {method,endpoint,headers: createHeaders(),};if (!isEmpty(options)) {data = {...data,...options,};if (options.json) {data.headers['Content-Type'] = 'application/json;charset=utf-8';data.body = JSON.stringify(options.json);}if (options.form) {data.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';data.body = serialize(options.form);}if (options.body) {data.body = options.body;const auth = JSON.parse(localStorage.getItem('auth'+sessionStorage.getItem("hid")));if (auth) {if (auth && options.body instanceof FormData && !options.body.hasPatientid) {// options.body.append('patientid', auth.Patientid);}}}if (options.params) {endpoint += `?${serialize(options.params)}`;data.endpoint = endpoint;}}return data;}// Response interceptor/* eslint-disable consistent-return */function interceptResponse(response) {return new Promise((resolve, reject) => {const emptyCodes = [204, 205];// Don't attempt to parse 204 & 205if (emptyCodes.indexOf(response.status) !== -1) {return resolve(response.ok);}if (response.ok) {const contentType = response.headers.get('Content-Type');if (contentType.includes('application/json')) {resolve(response.json());}resolve(response);}if (response.status === 401) {// return Toast.fail('认证信息已过期,请重新登录', 2, () => {// return Toast.fail('请重新登录', 2, () => {localStorage.removeItem('auth'+sessionStorage.getItem("hid"));// sessionStorage.removeItem('token');location.reload();// TODO:跳转登录路由// });}const error = new Error(response.statusText);try {response.clone().json().then((result) => {error.body = result;error.response = response;reject(error);});} catch (e) {error.response = response;reject(error);}});}/* eslint-enable consistent-return */// sugerrequest.get = (url, options) => request(url, options, 'GET');request.head = (url, options) => request(url, options, 'HEAD');request.options = (url, options) => request(url, options, 'OPTIONS');request.post = (url, options) => request(url, options, 'POST');request.put = (url, options) => request(url, options, 'PUT');request.delete = (url, options) => request(url, options, 'DELETE');request.del = request.delete;export default request;
5. 这样你就可以在今后的项目正常使用按照以下步骤
module.exports = {apiBaseUrl: "http://172.118.100.50/api/",};
之后再services文件下就可以这样去下啦:
import request from '../utils/request/request';export function queryScaleMenu(start, limit) {const body = new FormData();body.append('start',start);body.append('limit', limit);return request.post('news/menu/query', { body });}
简书地址: https://www.jianshu.com/p/007196101cf1
更新日期: 2018.01.24 18:49
