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

image.png
combineURL.js中 :
// Creates a new URL by combining the specified URLs
const combineURL = (baseUrl, path) => {
return `${baseUrl.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`;
};
export default combineURL;
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 */这个是dva自动生成的request.js 把这个文件换下名字requests.js,它与lang.js同级。
4. 打开在request文件下request.js,进行编辑:
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 & 205
if (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 });
}
作者:sidney_c
链接:https://www.jianshu.com/p/007196101cf1
随时随地看视频