作为一名前端,对数据的请求要掌握多少?
前端数据请求核心技能包括:掌握XMLHttpRequest、FetchAPI和Axios,熟练处理异步Promise和async/await,能应对错误处理、跨域问题及性能优化。文章还提供了手写Promise的实现方案,包含状态管理、异步处理、链式调用等核心特性,帮助开发者深入理解异步编程原理。掌握这些内容可应对大多数前端数据请求场景。
·
作为前端开发者,数据请求是核心技能之一,需要掌握的知识可以分为几个层次:
一、数据请求需要掌握的核心内容
-
基础请求方式
- 了解
XMLHttpRequest
的工作原理(虽然实际开发中很少直接用,但能帮助理解底层)。 - 熟练使用
Fetch API
(浏览器原生,基于 Promise),掌握其配置项(method、headers、body、credentials 等)。 - 熟悉主流请求库(如 Axios)的使用,包括拦截器、请求 / 响应配置、取消请求等高级功能。
- 了解
-
异步处理机制
- 深刻理解 Promise 的原理和使用(链式调用、错误捕获)。
- 熟练使用
async/await
语法简化异步代码。 - 处理并发请求(如
Promise.all
、Promise.race
等)。
-
错误与异常处理
- 网络错误(断网、超时)的捕获与处理。
- HTTP 错误状态码(4xx、5xx)的统一处理。
- 接口返回的业务错误(如权限不足、数据格式错误)的处理逻辑。
-
跨域问题
- 理解跨域的原因(浏览器同源策略)。
- 掌握常见跨域解决方案(CORS、JSONP、代理服务器等)。
-
请求优化
- 缓存策略(强缓存、协商缓存)。
- 请求合并、防抖节流(避免频繁请求)。
- 大文件分片上传、断点续传等场景处理。
二、手写 Promise(符合 Promise/A+ 规范核心特性)
Promise 是异步编程的解决方案,核心是状态管理(pending → fulfilled/rejected,状态不可逆)和链式调用。以下是一个简化实现:
class MyPromise {
// 构造函数接收执行器(executor)
constructor(executor) {
// 初始状态为pending
this.status = 'pending';
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
// 成功回调队列(处理异步情况)
this.onFulfilledCallbacks = [];
// 失败回调队列
this.onRejectedCallbacks = [];
// 成功回调(状态变为fulfilled)
const resolve = (value) => {
// 状态只能从pending改变
if (this.status === 'pending') {
this.status = 'fulfilled';
this.value = value;
// 执行所有缓存的成功回调
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
// 失败回调(状态变为rejected)
const reject = (reason) => {
if (this.status === 'pending') {
this.status = 'rejected';
this.reason = reason;
// 执行所有缓存的失败回调
this.onRejectedCallbacks.forEach(fn => fn());
}
};
// 执行器可能抛出错误,需要捕获
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then方法:接收成功和失败回调,返回新Promise实现链式调用
then(onFulfilled, onRejected) {
// 处理回调非函数的情况(值穿透)
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function'
? onRejected
: reason => { throw reason; };
// 返回新Promise,实现链式调用
const newPromise = new MyPromise((resolve, reject) => {
// 状态为fulfilled时执行
if (this.status === 'fulfilled') {
// 用setTimeout模拟异步(Promise回调需异步执行)
setTimeout(() => {
try {
// 执行成功回调,获取返回值
const result = onFulfilled(this.value);
// 解析返回值(如果是Promise则等待其完成,否则直接resolve)
this.resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
// 状态为rejected时执行
if (this.status === 'rejected') {
setTimeout(() => {
try {
const result = onRejected(this.reason);
this.resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
// 状态为pending时,缓存回调
if (this.status === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const result = onFulfilled(this.value);
this.resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const result = onRejected(this.reason);
this.resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return newPromise;
}
// 解析then回调的返回值(处理返回Promise的情况)
resolvePromise(newPromise, result, resolve, reject) {
// 避免循环引用(如then返回自身)
if (newPromise === result) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 如果返回值是Promise,等待其完成
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
// 非Promise直接resolve
resolve(result);
}
}
// 静态方法:快速创建成功的Promise
static resolve(value) {
return new MyPromise(resolve => resolve(value));
}
// 静态方法:快速创建失败的Promise
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
}
核心特性说明
- 状态管理:通过
pending
→fulfilled
/rejected
的不可逆状态,保证回调只执行一次。 - 异步处理:用
setTimeout
模拟微任务(实际 Promise 用微任务队列),确保回调异步执行。 - 链式调用:
then
方法返回新的 Promise,通过resolvePromise
处理回调返回值(支持返回 Promise 或普通值)。 - 值穿透:当
then
的参数不是函数时,会忽略该回调,直接将值传递给下一个then
。
掌握这些内容后,就能应对前端大部分数据请求场景,以及理解异步编程的核心逻辑了。
更多推荐
所有评论(0)