- 定义:ES6内置类,用于管理异步编程(本身同步,仅内部常包含异步操作);
- 核心作用:解决回调地狱,将异步流程以同步链式写法呈现;
- 核心概念:
- 状态(不可逆):
pending(初始)→ fulfilled(成功)/rejected(失败); - 结果值:
[[PromiseResult]] 存储成功结果或失败原因; - Executor函数:
new Promise(executor) 中立即执行的函数,接收 resolve(成功)和 reject(失败)两个参数。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('成功结果'), 1000);
});
const p2 = p1.then(
(result) => { console.log('成功:', result); return 200; },
(reason) => { console.log('失败:', reason); return -1; }
);
p2.catch(reason => console.log('异常:', reason));
- 新Promise状态由上一个
then/catch的执行结果决定:- 执行抛出异常 → 新状态为
rejected; - 返回新Promise → 继承其最终状态;
- 其他情况 → 新状态为
fulfilled,返回值作为结果。
| 方法 | 作用 | 特点 |
|---|
Promise.resolve(value) | 快速创建成功Promise | value为Promise则直接返回,为thenable对象则跟随其状态 |
Promise.reject(reason) | 快速创建失败Promise | 状态固定为rejected |
Promise.all(arr) | 并行执行多个Promise | 全部成功则返回结果数组,一个失败则直接失败 |
Promise.race(arr) | 多个Promise竞速 | 第一个完成的结果作为最终结果(无论成功失败) |
class MyPromise {
constructor(executor) {
this.status = 'pending';
this.value = undefined;
this.resolvedArr = [];
this.rejectedArr = [];
const changeStatus = (status, result) => {
if (this.status !== 'pending') return;
this.status = status;
this.value = result;
const callbackArr = status === 'fulfilled' ? this.resolvedArr : this.rejectedArr;
callbackArr.forEach(fn => fn(this.value));
};
const resolve = (result) => {
setTimeout(() => changeStatus('fulfilled', result), 0);
};
const reject = (reason) => {
setTimeout(() => changeStatus('rejected', reason), 0);
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(resolvedFn, rejectedFn) {
resolvedFn = typeof resolvedFn === 'function' ? resolvedFn : (v) => v;
rejectedFn = typeof rejectedFn === 'function' ? rejectedFn : (e) => { throw e; };
return new MyPromise((resolve, reject) => {
this.resolvedArr.push((value) => {
try {
const x = resolvedFn(value);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
});
this.rejectedArr.push((reason) => {
try {
const x = rejectedFn(reason);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
});
});
}
catch(rejectedFn) {
return this.then(null, rejectedFn);
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let completedCount = 0;
promises.forEach((p, index) => {
MyPromise.resolve(p).then(
(result) => {
results[index] = result;
completedCount++;
if (completedCount === promises.length) resolve(results);
},
(reason) => reject(reason)
);
});
});
}
}
- 构造函数(executor)同步执行,
then/catch回调异步执行(微任务); await 本质是Promise语法糖,仅处理成功状态,失败需配合try/catch;- 异常捕获:
catch后可继续链式调用then,且仅执行成功回调(因catch返回成功状态Promise)。
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => console.log('setTimeout'), 0);
async1();
new Promise((resolve) => {
console.log('promise1');
resolve();
}).then(() => console.log('promise2'));
console.log('script end');
- 同步代码优先:
script start → async1 start → async2 → promise1 → script end; - 微任务执行:
promise2 → async1 end; - 宏任务执行:
setTimeout; - 最终输出:
script start → async1 start → async2 → promise1 → script end → promise2 → async1 end → setTimeout。
| 方案 | 核心特点 | 适用场景 |
|---|
| Ajax(XHR) | 同源通信,基于HTTP/HTTPS,异步无刷新 | 同源下数据请求 |
| Fetch | 基于Promise,原生API,更底层 | 现代浏览器异步请求 |
| Axios | 基于XHR封装,支持Promise/拦截器/取消请求 | 前后端分离项目首选 |
| WebSocket | 全双工通信,服务器主动推送,无同源限制 | 实时通信(如聊天、监控) |
| Form表单提交 | 同步刷新页面,支持跨域,无需JS | 简单数据提交(无实时交互需求) |
| 特性 | Axios | Fetch |
|---|
| 异常处理 | 400/500状态码会触发reject | 仅网络错误触发reject,400/500视为成功 |
| Cookie携带 | 默认携带 | 需手动配置credentials: 'include' |
| 超时控制 | 原生支持timeout参数 | 需结合Promise.race手动实现 |
| 响应转换 | 自动转换JSON数据 | 需手动调用response.json() |
| 中断请求 | 支持CancelToken | 需用AbortController |
- 协议标识:
ws(明文)/wss(加密),基于TCP协议; - 无同源限制,支持二进制/文本数据传输;
- 适用场景:实时聊天、股票行情、物联网监控。
- FormData:HTML5新增API,用于序列化表单数据或异步上传文件,
Content-Type: multipart/form-data; - 表单跨域:表单可直接跨域提交(浏览器兼容特性),但无法获取跨域响应数据;
- 实战示例:
const form = document.querySelector('#form');
const formData = new FormData(form);
formData.append('extra', '额外数据');
axios.post('/api/submit', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
- 跨域:协议、域名、端口任一不同即构成跨域,浏览器默认阻止跨域JS数据交互;
- 同源策略:限制不同源页面的JS访问,保护用户数据安全。
| 方案 | 核心原理 | 适用场景 |
|---|
| CORS | 服务器设置响应头(如Access-Control-Allow-Origin)允许跨域 | 现代前后端分离项目(推荐) |
| JSONP | 利用<script>标签无跨域限制,加载回调函数包裹的JSON数据 | 老旧浏览器兼容,仅支持GET请求 |
| 代理转发 | 本地代理(webpack-dev-server)/Nginx反向代理,规避浏览器跨域限制 | 开发环境/生产环境通用 |
| document.domain | 主域名相同,子域名间设置document.domain统一域名 | 子域名跨域(如a.xxx.com与b.xxx.com) |
| postMessage | 跨窗口/iframe通信API,允许不同源页面传递数据 | 跨窗口/iframe交互 |
- 服务器配置(以Node.js为例):
res.setHeader('Access-Control-Allow-Origin', 'https://xxx.com');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE');
res.setHeader('Access-Control-Allow-Credentials', 'true');
- 客户端配置(Axios):
axios.get('/api/data', { withCredentials: true });
- 简单请求vs复杂请求:
- 简单请求:GET/POST/HEAD,请求头仅含默认字段(如
Accept),无预请求; - 复杂请求:PUT/DELETE、自定义请求头、
Content-Type: application/json,会先发送OPTIONS预请求验证权限。
function jsonpCallback(data) {
console.log('跨域数据:', data);
}
const script = document.createElement('script');
script.src = 'https://api.xxx.com/data?callback=jsonpCallback';
document.body.appendChild(script);
jsonpCallback({ name: 'xxx', value: 'xxx' });
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://api.xxx.com',
changeOrigin: true,
pathRewrite: { '^/api': '' }
}
}
}
};
- JSONP不支持POST:本质是
<script>标签加载,仅支持GET请求; - 跨域允许场景:表单提交、
<script>/<img>等标签加载资源(无响应数据获取); - 生产环境优先:CORS(简单配置)或Nginx反向代理(性能优)。
| 特性 | GET | POST | PUT |
|---|
| 参数位置 | URL拼接 | 请求体 | 请求体 |
| 缓存 | 浏览器主动缓存 | 需手动配置 | 需手动配置 |
| 幂等性 | 是(多次请求结果一致) | 否 | 是(更新资源,多次执行结果一致) |
| 用途 | 查询资源 | 新增资源 | 更新资源 |
| 数据大小限制 | 依赖URL长度(通常2KB) | 无限制 | 无限制 |
- 同步异常:
try/catch捕获代码执行错误(无法捕获语法错误); - 异步异常:
- Promise:
catch方法捕获; - 全局捕获:
window.onerror(捕获所有运行时错误,返回true阻止控制台报错);
- 网络异常:Axios/Fetch拦截器捕获请求失败。
- Promise核心:状态不可逆,链式调用解决回调地狱,
then/catch返回新Promise; - 异步执行顺序:同步代码 → 微任务(Promise.then/await) → 宏任务(setTimeout/Ajax);
- 跨域首选方案:CORS(简单配置)、Nginx代理(生产环境)、JSONP(兼容老旧浏览器);
- 前后端通信工具:Axios(功能全、易用性高),Fetch(原生无依赖),WebSocket(实时通信)。