前端网络请求实战总结:从踩坑到优化的全过程解析
我的写法,亲测靠谱
在网络请求这块,我一般用fetch和axios这两种方式。这俩各有优劣,但总的来说,fetch更原生,适合一些简单的需求,而axios则功能更强大,配置更灵活。
先说fetch,这个API是现代浏览器自带的,不需要额外引入库,写起来也挺简单的。比如,一个基本的GET请求:
fetch('https://jztheme.com/api/data')
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
这种写法的好处是代码简洁,而且浏览器支持得也不错。但有一个坑,就是fetch默认不带credentials,所以如果你需要跨域请求并且要带上cookie,记得加上credentials: 'include':
fetch('https://jztheme.com/api/data', {
credentials: 'include'
})
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
再来说说axios,这个库功能更多,配置也更灵活。比如,同样的GET请求:
import axios from 'axios';
axios.get('https://jztheme.com/api/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
看起来差不多,但axios的配置项更多,比如可以设置超时时间、请求头等。我个人比较喜欢用axios的原因是它对错误处理更友好,特别是对于网络请求失败的情况,可以直接捕获到错误。
另外,axios还支持拦截器,可以在请求发送前和响应返回后做一些统一的处理。比如,全局设置请求头:
axios.interceptors.request.use(config => {
config.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`;
return config;
}, error => {
return Promise.reject(error);
});
这样每次请求都会自动带上认证信息,不用在每个请求里都写一遍。
这几种错误写法,别再踩坑了
说完了好的写法,再来说说常见的错误写法。这些坑我踩过好多次,希望大家能避开。
1. 忽略错误处理
很多新手开发者在写网络请求时,经常忽略错误处理。比如这样的代码:
fetch('https://jztheme.com/api/data')
.then(response => response.json())
.then(data => {
console.log(data);
});
这种写法的问题在于,如果请求失败或者解析JSON出错,你根本不知道问题出在哪里。正确的做法是在catch中捕获错误:
fetch('https://jztheme.com/api/data')
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
2. 不检查响应状态码
有时候,即使请求成功了,服务器也可能返回404或500这样的错误状态码。这时候,你需要检查响应的状态码,而不是直接使用数据:
fetch('https://jztheme.com/api/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
3. 不处理跨域问题
跨域请求是很常见的问题,特别是在开发阶段。如果你的请求跨域了,但没有正确配置CORS,那么请求会直接失败。比如:
fetch('https://anotherdomain.com/api/data')
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
这种情况下,你可能会看到类似“No ‘Access-Control-Allow-Origin’ header is present on the requested resource”的错误。解决办法是确保服务器端设置了正确的CORS头,或者使用代理(如http-proxy-middleware)来绕过跨域限制。
实际项目中的坑
在实际项目中,网络请求的复杂度往往比示例代码高得多。这里分享几个我在项目中遇到的坑和解决方法。
1. 请求超时问题
有时候,网络请求可能因为各种原因卡住,导致用户等待时间过长。为了解决这个问题,可以设置请求超时。比如,在axios中:
axios.get('https://jztheme.com/api/data', {
timeout: 5000
})
.then(response => {
console.log(response.data);
})
.catch(error => {
if (error.code === 'ECONNABORTED') {
console.error('Request timed out');
} else {
console.error('Error:', error);
}
});
这样,如果请求超过5秒还没有返回,就会触发超时错误。
2. 并发请求管理
在某些场景下,你可能需要同时发起多个请求,并且希望所有请求都成功后再做下一步操作。这时候,可以使用Promise.all来管理并发请求:
const requests = [
fetch('https://jztheme.com/api/data1'),
fetch('https://jztheme.com/api/data2'),
fetch('https://jztheme.com/api/data3')
];
Promise.all(requests)
.then(responses => Promise.all(responses.map(response => response.json())))
.then(data => {
console.log(data); // [data1, data2, data3]
})
.catch(error => {
console.error('Error:', error);
});
这样,所有的请求都会并发执行,只有当所有请求都成功后才会继续处理数据。
3. 请求取消
有时候,用户可能在请求过程中取消了操作,比如切换页面或者点击了取消按钮。为了防止不必要的请求,可以使用AbortController来取消请求:
const controller = new AbortController();
const signal = controller.signal;
fetch('https://jztheme.com/api/data', { signal })
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
if (error.name === 'AbortError') {
console.error('Request was aborted');
} else {
console.error('Error:', error);
}
});
// 在某个地方取消请求
controller.abort();
这样,当调用controller.abort()时,请求会被取消,避免了不必要的网络开销。
总结一下
以上是我个人在网络请求方面的一些实战经验和踩坑总结。希望对你有帮助。如果你有更好的实现方式或者补充,欢迎评论区交流。
