你是一位前端架构师,写一份axios封装的文章
好的,下面是一份关于如何封装 Axios 的文章。
Axios 是一个非常流行的用于发送 HTTP 请求的 JavaScript 库。它提供了许多功能和选项,使得它非常适合在前端应用程序中使用。然而,使用 Axios 进行网络请求时需要编写大量的重复代码,因此封装 Axios 是一个很好的做法,可以减少代码量并提高可读性。
下面是一份基本的 Axios 封装方案:
首先,我们需要创建一个 axios.js 文件,并在其中导入 Axios:
import axios from 'axios';
接下来,我们可以创建一个 axios 实例,设置一些默认选项和拦截器。我们可以将这些默认选项和拦截器用于每个请求:
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
});
instance.interceptors.request.use(
(config) => {
// 在请求发送之前做些什么
return config;
},
(error) => {
// 处理请求错误
return Promise.reject(error);
}
);
instance.interceptors.response.use(
(response) => {
// 处理响应数据
return response;
},
(error) => {
// 处理响应错误
return Promise.reject(error);
}
);
在上面的代码中,我们创建了一个 axios 实例,并设置了 baseURL 和 timeout 选项。我们还添加了一个请求拦截器和一个响应拦截器。请求拦截器用于在请求发送之前修改请求配置或者添加一些请求头信息,而响应拦截器用于在获取到响应后对响应数据进行处理。
接下来,我们可以编写一些方法来发送 GET、POST、PUT、DELETE 等类型的请求。例如,下面是一个发送 GET 请求的方法:
export const get = (url, params = {}) => {
return instance.get(url, {
params,
});
};
在上面的代码中,我们导出了一个 get 方法,用于发送 GET 请求。该方法接收一个 URL 和一个可选的参数对象作为参数,并使用 Axios 实例的 get 方法发送请求。
我们可以使用类似的方式来编写其他请求方法:
export const post = (url, data = {}) => {
return instance.post(url, data);
};
export const put = (url, data = {}) => {
return instance.put(url, data);
};
export const del = (url) => {
return instance.delete(url);
};
最后,我们可以将这些方法封装到一个统一的 api.js 文件中,并导出它们,以便在我们的应用程序中使用:
import { get, post, put, del } from './axios';
export const getUser = (id) => {
return get(`/user/${id}`);
};
export const createUser = (data) => {
return post('/user', data);
};
export const updateUser = (id, data) => {
return put(`/user/${id}`, data);
};
export const deleteUser = (id) => {
return del(`/user/${id
继续
这样,我们就可以在我们的应用程序中使用上述方法来发送请求:
import { getUser, createUser, updateUser, deleteUser } from './api';
getUser(1)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
createUser({ name: 'John Doe', email: 'john.doe@example.com' })
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
updateUser(1, { name: 'Jane Doe', email: 'jane.doe@example.com' })
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
deleteUser(1)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
总的来说,封装 Axios 可以使代码更加简洁和易于维护。通过创建一个 axios 实例和一些封装方法,我们可以在我们的应用程序中重复使用这些代码,而不必每次都重新编写一遍。此外,通过添加请求拦截器和响应拦截器,我们可以在发送和接收请求时添加一些公共的逻辑,从而提高代码的可重用性。
继续
除了上面的基本封装,我们还可以添加一些其他的功能和选项来满足不同的需求。
一种常见的需求是处理错误。我们可以在响应拦截器中添加一些错误处理逻辑,例如:
instance.interceptors.response.use(
(response) => {
// 处理响应数据
return response;
},
(error) => {
// 处理响应错误
if (error.response) {
// 响应状态码不为 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// 请求已发送但没有收到响应
console.log(error.request);
} else {
// 发生了一些错误,无法处理请求
console.log('Error', error.message);
}
console.log(error.config);
return Promise.reject(error);
}
);
在上面的代码中,我们添加了一个响应拦截器来处理响应错误。如果响应状态码不是 2xx,则输出一些错误信息。如果请求已经发送但没有收到响应,则输出请求信息。最后,如果发生了其他错误,则输出错误消息。
另一个常见的需求是添加身份验证信息。我们可以使用 Axios 的拦截器来添加身份验证令牌到请求头中:
import { getToken } from './auth';
instance.interceptors.request.use(
(config) => {
const token = getToken();
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
在上面的代码中,我们添加了一个请求拦截器来添加身份验证令牌到请求头中。我们从另一个文件中导入了一个名为 getToken 的方法,该方法返回当前用户的身份验证令牌。如果令牌存在,则将其添加到请求头中,以便服务器可以验证用户的身份。
还有很多其他的功能和选项可以添加到 Axios 封装中,例如取消请求、缓存数据等。根据项目的实际需求和开发团队的偏好,可以根据需要自定义和扩展 Axios 的封装。
继续
另外,我们也可以为 Axios 封装添加一些基于业务需求的功能,例如:
- 统一的请求错误处理:根据业务需求,可能需要将一些特定类型的错误转换成自定义的错误信息。这可以通过在响应拦截器中对错误进行分类和处理来实现。
- 请求超时处理:在一些复杂的网络环境下,可能会出现请求超时或者网络不稳定的情况。我们可以通过配置 Axios 的 timeout 选项来设置请求超时时间,以及通过响应拦截器捕获请求超时的错误,并重新发送请求或者提示用户。
- 自动重试:在网络不稳定或者服务器压力过大的情况下,请求可能会失败。我们可以通过配置 Axios 的 retry 选项来设置自动重试的次数和间隔时间,以提高请求的成功率。
- 请求缓存:对于一些请求数据不经常变化的接口,我们可以考虑将请求结果进行缓存,以避免重复请求和减少服务器压力。
- 请求队列管理:在一些复杂的场景下,可能会出现多个请求同时发出,但需要保证这些请求的执行顺序和正确性。我们可以通过使用 Axios CancelToken 和 Promise.race() 来实现请求队列的管理,以保证请求的有序执行。
最后,需要注意的是,封装 Axios 并不是一劳永逸的工作。随着项目的不断发展和需求的变化,我们需要不断优化和扩展 Axios 的封装,以满足项目的实际需求。同时,我们也可以参考一些成熟的 Axios 封装库,例如 axios-mock-adapter、axios-cache-adapter、axios-retry 等,来加速我们的开发和提高代码质量。
写一下基于业务需求功能的部分
好的,下面我将进一步介绍一些基于业务需求的功能和选项,以便更好地满足项目的实际需求。
- 统一的请求错误处理
在实际项目中,我们可能需要针对不同的错误类型,采取不同的处理方式。例如,对于一些用户认证失败的错误,我们可能需要将其转换成自定义的错误信息并提示用户重新登录;而对于一些请求参数错误的错误,我们可能需要将其转换成更加友好的错误提示信息。为了方便统一管理这些错误处理逻辑,我们可以在 Axios 封装中添加一个统一的错误处理方法,例如:
function handleError(error) {
if (error.response) {
switch (error.response.status) {
case 401:
// 用户未登录或者认证失败
// 转换成自定义错误信息并提示用户重新登录
break;
case 404:
// 请求的资源不存在
// 转换成更加友好的错误提示信息
break;
case 500:
// 服务器内部错误
// 转换成更加友好的错误提示信息
break;
default:
// 其他错误
// 转换成更加友好的错误提示信息
break;
}
} else if (error.request) {
// 请求已发送但没有收到响应
// 转换成更加友好的错误提示信息
} else {
// 发生了一些错误,无法处理请求
// 转换成更加友好的错误提示信息
}
// 返回自定义的错误对象
return Promise.reject(new Error('请求出错'));
}
// 在响应拦截器中使用统一的错误处理方法
instance.interceptors.response.use(
(response) => {
// 处理响应数据
return response;
},
(error) => {
// 处理响应错误
return handleError(error);
}
);
在上面的代码中,我们添加了一个名为 handleError 的错误处理方法,并在响应拦截器中调用它来统一处理错误。在 handleError 方法中,我们根据不同的错误类型进行分类处理,并将其转换成自定义的错误信息。最后,返回自定义的错误对象,以便在调用方处统一处理。
- 请求超时处理
在一些复杂的网络环境下,请求可能会因为网络不稳定或者服务器压力过大等原因,导致请求超时或者长时间没有响应。为了避免这种情况,我们可以通过配置 Axios 的 timeout 选项来设置请求超时时间,并在响应拦截器中捕获请求超时的错误并进行处理。例如:
instance.defaults.timeout = 5000; // 设置请求超时时间为 5 秒
// 在响应拦截器中捕获请求超时的错误并进行处理
instance.interceptors.response.use( (response) => {
// 处理响应数据
return response;
}, (error) => {
// 处理响应错误
if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
// 请求超时,转换成自定义错误信息并提示用户
} else {
// 其他错误,统一处理
return handleError(error);
} } );
在上面的代码中,我们通过设置 instance.defaults.timeout 来设置请求超时时间,当请求超过这个时间时,Axios 将自动中断请求并抛出一个错误。在响应拦截器中,我们捕获这个错误并判断它的 code 属性是否为 ECONNABORTED,并且 message 属性是否包含 timeout 字符串,以判断是否为请求超时错误。如果是请求超时错误,我们将其转换成自定义的错误信息并提示用户;否则,我们将其交给 handleError 方法进行统一处理。
- 文件上传和下载
在一些项目中,我们可能需要进行文件上传和下载的操作。Axios 提供了对于文件上传和下载的支持,我们可以通过配置 headers、data 和 responseType 等选项来实现这些功能。例如,以下是一个文件上传的例子:
function uploadFile(file, url) {
const formData = new FormData();
formData.append('file', file);
return instance.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
在上面的代码中,我们首先创建了一个 FormData 对象,将要上传的文件添加到其中,并将其作为请求体传递给 Axios。在配置中,我们通过设置 headers 选项来指定请求体的类型为 multipart/form-data,以支持文件上传操作。当请求成功时,Axios 将返回一个响应对象,其中包含了上传文件的相关信息。
类似地,以下是一个文件下载的例子:
function downloadFile(url) {
return instance.get(url, {
responseType: 'blob',
});
}
在上面的代码中,我们通过设置 responseType 选项为 blob 来支持文件下载操作。当请求成功时,Axios 将返回一个响应对象,其中包含了下载文件的二进制数据。
- 取消请求
在一些情况下,我们可能需要取消正在进行的请求,例如用户取消了某个操作或者页面跳转了等等。为了支持请求的取消,Axios 提供了 CancelToken 的概念,我们可以通过创建 CancelToken 实例并将其作为请求配置中的 cancelToken 选项来实现请求的取消。例如:
import { CancelToken } from 'axios';
let cancel;
function fetchData() {
const source = CancelToken.source();
instance.get('/api/data', {
cancelToken: source.token
}).then((response) => {
// 处理响应数据
}).catch((error) => { /
/ 处理响应错误
if (axios.isCancel(error)) {
// 请求被取消
} else {
// 其他错误,统一处理
return handleError(error);
}
});
// 取消请求
function cancelRequest() { cancel && cancel('请求已被取消'); }
export { fetchData, cancelRequest };
在上面的代码中,我们首先引入了 Axios 中的 CancelToken 模块,并定义了一个 cancel 变量用于存储取消请求的函数。在 fetchData 方法中,我们通过创建 CancelToken 的实例 source,并将其 token 属性作为请求配置的 cancelToken 选项,从而实现了请求的取消功能。在响应拦截器中,我们判断错误是否为取消请求的错误,并根据需要进行处理。
最后,我们定义了一个 cancelRequest 函数,用于手动取消请求。当我们调用这个函数时,cancel 变量中保存的取消函数将被调用,请求将被取消并返回一个包含错误信息的 Promise 对象。我们可以在捕获到这个错误后进行相应的处理。
总结
本文介绍了如何封装 Axios,以适应不同的业务需求。我们通过自定义配置、拦截器、请求超时、文件上传和下载、请求取消等功能来满足各种业务场景下的需求。Axios 是一款功能强大且易于使用的 HTTP 客户端库,它不仅能够方便地处理 HTTP 请求和响应,还能够与现代前端框架、Node.js 等平台无缝集成,是我们进行 Web 开发不可缺少的工具之一。