JavaScript网络请求可以通过封装来简化代码,提高代码的可维护性和可复用性。
以下是一些常见的封装方式:
一、使用XMLHttpRequest对象进行封装
XMLHttpRequest对象是JavaScript中用于发送HTTP请求的核心对象。可以通过封装XMLHttpRequest对象来实现网络请求的封装。例如:
function request(method, url, data, callback) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()); // 添加token验证
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
callback(null, JSON.parse(xhr.responseText));
} else {
callback(new Error(xhr.statusText));
}
}
};
xhr.send(JSON.stringify(data));
}
function getToken() { // 获取token的逻辑
return 'your_token_here';
}
// 使用示例
request('GET', '<https://api.example.com/data>', null, function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
在上面的示例中,我们通过xhr.setRequestHeader方法添加了一个Authorization头部,值为Bearer加上我们获取到的token。
这样,在发送请求时,服务器就会验证我们的token是否有效。如果token无效,服务器会返回401或403状态码,我们可以在onreadystatechange回调函数中处理这种情况。
二、使用第三方库进行封装
JavaScript中有很多第三方库可以用于网络请求的封装,例如Axios、Fetch、jQuery、Superagent等。这些库已经封装了网络请求的细节,可以直接调用其API来发送网络请求。
2.1 Axios网络封装
Axios是一个基于Promise的HTTP客户端,用于浏览器和Node.js。它具有以下特点:
- 支持浏览器和Node.js环境。
- 支持Promise API。
- 支持拦截请求和响应。
- 支持取消请求。
- 支持自动转换JSON数据。
- 支持客户端防御XSRF攻击。
Axios的网络封装具体细节如下:
- 创建实例 在使用Axios发送请求之前,需要先创建一个Axios实例。可以通过Axios.create()方法创建一个实例,也可以直接使用全局的Axios实例。
import axios from 'axios';
const instance = axios.create({
baseURL: '<https://api.example.com>',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
- 发送请求 Axios支持多种请求方式,包括GET、POST、PUT、DELETE等。可以通过调用实例的相应方法来发送请求。
instance.get('/user?ID=12345')
.then(function (response) {
console.log(response); })
.catch(function (error) {
console.log(error);
});
- 拦截请求和响应 Axios支持拦截请求和响应,可以在请求或响应被发送或接收之前对它们进行拦截和处理。可以通过调用实例的interceptors属性来添加拦截器。
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
- 取消请求 Axios支持取消请求,可以在请求还未完成时取消它。可以通过调用实例的cancelToken属性来创建一个取消令牌,然后将它传递给请求配置中的cancelToken属性。
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
instance.get('/user', {
cancelToken: source.token }).catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
// 取消请求
source.cancel('Operation canceled by the user.');
- 自动转换JSON数据 Axios支持自动转换JSON数据,可以将请求和响应中的JSON数据自动转换为JavaScript对象。可以通过设置实例的transformRequest和transformResponse属性来实现自动转换。
instance.defaults.transformRequest = [function (data) { return qs.stringify(data); }];
instance.defaults.transformResponse = [function (data) { return JSON.parse(data); }];
- 客户端防御XSRF攻击 Axios支持客户端防御XSRF攻击,可以通过设置实例的xsrfCookieName和xsrfHeaderName属性来实现。xsrfCookieName属性用于设置存储XSRF令牌的cookie的名称,xsrfHeaderName属性用于设置发送XSRF令牌的HTTP头的名称。
instance.defaults.xsrfCookieName = 'XSRF-TOKEN';
instance.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';
以下是一个基于axios的网络请求封装,包含了token验证
import axios from 'axios';
const instance = axios.create({
baseURL: '<https://api.example.com>', timeout: 10000,
});
// 请求拦截器
instance.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, (error) => {
return Promise.reject(error);
});
// 响应拦截器
instance.interceptors.response.use((response) => {
return response.data;
}, (error) => {
if (error.response) {
switch (error.response.status) {
case 401:
// token失效,跳转到登录页
localStorage.removeItem('token');
window.location.href = '/login';
break;
case 404:
// 404错误处理
break;
default:
// 其他错误处理
break;
}
}
return Promise.reject(error);
});
export default instance;
在请求拦截器中,我们从localStorage中获取token,并将其添加到请求头中。在响应拦截器中,我们对token失效的情况进行了处理,将用户跳转到登录页。其他错误情况可以根据实际需求进行处理。
2.2 使用Fetch API进行封装
- 创建一个封装函数,接收请求的参数,如请求的URL、请求方法、请求头、请求体等。
function fetchApi(url, method, headers, body) {
// ...
}
- 在函数内部使用Fetch API发送请求,并返回一个Promise对象。
function fetchApi(url, method, headers, body) {
return fetch(url, {
method: method, headers: headers, body: body
});
}
- 处理请求的响应,根据响应状态码判断请求是否成功,并将响应数据转换为JSON格式。
function fetchApi(url, method, headers, body) {
return fetch(url, {
method: method, headers: headers, body: body
}).then(response => {
if (!response.ok) {
throw new Error(response.statusText);
}
return response.json();
});
}
- 在函数中处理请求失败的情况,如网络错误或服务器错误。
function fetchApi(url, method, headers, body) {
return fetch(url, {
method: method, headers: headers, body: body
}).then(response => {
if (!response.ok) {
throw new Error(response.statusText);
}
return response.json();
}).catch(error => {
console.error('Fetch API error:', error);
});
}
- 最终的封装函数代码示例:
function fetchApi(url, method, headers, body) {
return fetch(url, {
method: method, headers: headers, body: body
}).then(response => {
if (!response.ok) {
throw new Error(response.statusText);
}
return response.json();
}).catch(error => {
console.error('Fetch API error:', error);
});
}
以下是一个基于Featch API的网络请求封装,包含了token验证
const API_BASE_URL = '<https://example.com/api>';
function fetchAPI(endpoint, options = {}) {
const token = localStorage.getItem('token');
const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
};
const url = `${API_BASE_URL}/${endpoint}`;
return fetch(url, { ...options, headers }).then((response) => {
if (!response.ok) {
throw new Error(response.statusText);
}
return response.json();
}).catch((error) => {
console.error(error);
});
}
// 使用示例
fetchAPI('users') .then((data) => {
console.log(data);
}).catch((error) => {
console.error(error);
});
在上面的示例中,我们定义了一个 fetchAPI 函数,它接受一个 endpoint 参数和一个可选的 options 参数。
我们使用 localStorage 获取存储在客户端的 token,并将其添加到请求头中的 Authorization 字段中。
然后,我们使用 fetch 函数发出网络请求,并在响应不是 200 OK 时抛出一个错误。
最后,我们返回响应的 JSON 数据。 在使用 fetchAPI 函数时,我们只需要传递 endpoint 参数即可。
如果需要传递其他选项,可以将它们作为第二个参数传递。例如,如果要发出 POST 请求并传递数据,可以这样做:
fetchAPI('users', {
method: 'POST',
body: JSON.stringify({ name: 'John Doe' }),
}).then((data) => {
console.log(data);
}).catch((error) => {
console.error(error);
});
2.3 使用jQuery封装网络请求
- 创建一个封装网络请求的函数,例如:
function ajaxRequest(url, method, data, successCallback, errorCallback) {
// 网络请求代码
}
- 在函数中使用jQuery的ajax方法发送网络请求,例如:
function ajaxRequest(url, method, data, successCallback, errorCallback) {
$.ajax({
url: url,
method: method,
data: data,
success: successCallback,
error: errorCallback
});
}
- 在函数中添加参数,例如:
function ajaxRequest(url, method, data, successCallback, errorCallback, headers) {
$.ajax({
url: url,
method: method,
data: data,
headers: headers,
success: successCallback,
error: errorCallback
});
}
- 在函数中添加默认参数,例如:
function ajaxRequest(url, method, data, successCallback, errorCallback, headers) {
headers = headers || {};
$.ajax({
url: url,
method: method,
data: data,
headers: headers,
success: successCallback,
error: errorCallback
});
}
- 在函数中添加请求超时时间,例如:
function ajaxRequest(url, method, data, successCallback, errorCallback, headers, timeout) {
headers = headers || {};
timeout = timeout || 5000;
$.ajax({
url: url,
method: method,
data: data,
headers: headers,
timeout: timeout,
success: successCallback,
error: errorCallback
});
}
- 在函数中添加请求类型,例如:
function ajaxRequest(url, method, data, successCallback, errorCallback, headers, timeout, dataType) {
headers = headers || {};
timeout = timeout || 5000;
dataType = dataType || 'json';
$.ajax({
url: url,
method: method,
data: data,
headers: headers,
timeout: timeout,
dataType: dataType,
success: successCallback,
error: errorCallback
});
}
- 最终的封装代码示例:
function ajaxRequest(url, method, data, successCallback, errorCallback, headers, timeout, dataType) {
headers = headers || {};
timeout = timeout || 5000;
dataType = dataType || 'json';
$.ajax({
url: url,
method: method,
data: data,
headers: headers,
timeout: timeout,
dataType: dataType,
success: successCallback,
error: errorCallback
});
}
以下是一个简单的jQuery网络请求封装,带有token验证
function requestWithToken(method, url, data, successCallback, errorCallback) {
var token = localStorage.getItem('token'); // 从本地存储中获取token
$.ajax({
method: method,
url: url,
data: data,
headers: {
'Authorization': 'Bearer ' + token // 在请求头中添加token
},
success: function(response) {
successCallback(response);
},
error: function(error) {
errorCallback(error);
}
});
}
使用方法:
requestWithToken('GET', '/api/data', null, function(response) {
console.log(response);
}, function(error) {
console.log(error);
});
在请求头中添加token可以确保请求的安全性,只有携带正确的token才能访问受保护的资源。同时,将token存储在本地存储中可以避免每次请求都需要重新输入token的麻烦。
2.4 使用封装网络请求
- 安装Superagent
npm install superagent --save
- 创建一个封装请求的函数
import request from 'superagent';
const API_ROOT = '<https://api.example.com>';
function handleErrors(err) {
if (err && err.response && err.response.status === 401) {
// 处理未授权的错误
} else {
// 处理其他错误
}
}
function requestWrapper(method, url, data) {
const req = request[method.toLowerCase()]();
if (data) {
req.send(data);
}
return req.then((res) => {
return res.body;
}).catch((err) => {
handleErrors(err);
throw err;
});
}
export default requestWrapper;
- 使用封装的请求函数
import request from './requestWrapper';
// GET 请求
request('get', '/users').then((data) => {
console.log(data);
}).catch((err) => {
console.error(err);
});
// POST 请求
request('post', '/users', { name: 'John Doe', email: '<john@example.com>' }).then((data) => {
console.log(data);
}).catch((err) => {
console.error(err);
});
以下是使用Superagent进行网络请求封装并带有token验证的示例代码
import request from 'superagent';
const API_ROOT = '<https://example.com/api>';
const token = 'your_token_here';
const handleResponse = (res) => {
if (!res.ok) {
throw new Error(res.body.message);
}
return res.body;
};
const get = (url) => {
return request
.get(`${API_ROOT}${url}`)
.set('Authorization', `Bearer ${token}`)
.then(handleResponse);
};
const post = (url, data) => {
return request
.post(`${API_ROOT}${url}`)
.set('Authorization', `Bearer ${token}`)
.send(data) .then(handleResponse);
};
const put = (url, data) => {
return request
.put(`${API_ROOT}${url}`)
.set('Authorization', `Bearer ${token}`)
.send(data)
.then(handleResponse);
};
const del = (url) => {
return request
.delete(`${API_ROOT}${url}`)
.set('Authorization', `Bearer ${token}`)
.then(handleResponse);
};
export default { get, post, put, del, };
在上面的代码中,我们首先定义了API的根路径和token。然后,我们定义了四个函数:get、post、put和del,分别对应HTTP的GET、POST、PUT和DELETE方法。这些函数都接受一个URL和一个可选的数据对象作为参数,并使用Superagent发送网络请求。在每个请求中,我们都设置了Authorization头,将token作为Bearer令牌发送。最后,我们导出这些函数,以便在其他地方使用。