写在前面:
兄弟们,我手里有个长期项目,考虑接私活的可以看看我GitHub!
https://github.com/ccy-233/coder2retire
pending
、fulfilled
、rejected
,状态一旦改变不可逆 。.then()
和 .catch()
。Promise.all()
:所有 Promise 成功时返回结果数组,任一失败立即拒绝 。Promise.race()
:首个完成的 Promise 决定最终状态 。Promise.resolve()
/Promise.reject()
:快速创建成功/失败的 Promise 。Promise.all
和 Promise.race
的实现 。本质:基于 Generator 和 Promise 的语法糖,使异步代码更接近同步写法 。
规则:
async
函数返回 Promise 对象,return
值会被 Promise.resolve()
包装 。await
后接 Promise,暂停当前函数执行直到 Promise 完成(属于微任务)。await
只能在 async
函数内使用,否则需通过立即调用异步函数(如 (async () => { ... })()
)。错误处理:用 try...catch
捕获 await
后的 Promise 拒绝 。
执行顺序:await
后的代码相当于放入 .then()
中,属于微任务队列 。
function asyncToGenerator(fn) {
// 返回函数
return function() {
const gen = fn.apply(this, arguments);//生成器
// 方法返回一个Promise对象
return new Promise((resolve, reject) => {
function step(key, arg) {
// console.log(arg)
let result;
try {
result = genkey;
//生成器返回数据{value,done:bool}
// 移除调试日志以保持输出整洁
} catch (error) {
return reject(error);
}
//如果执行器执行完成
if (result.done) {
return resolve(result.value);
}
//如果执行器未完成,将当前结果传入Promise的resolve方法中,并递归调用step方法
Promise.resolve(result.value).then(
v => step(“next”, v),
e => step(“throw”, e)
);
}
step(“next”);
});
};
}
// 使用示例(已修复)
const asyncFunction = asyncToGenerator(function* () {
// 修正 Promise 的创建方式,使用箭头函数包裹 resolve
const result = yield new Promise(resolve => setTimeout(() => resolve(“result”), 1000));
const result1 = yield new Promise(resolve => setTimeout(() => resolve(“result2”), 2000));
console.log(result, result1); // 输出: “result” “result2”(3秒后)
});
asyncFunction(); // 启动执行
定义:将多参数函数转换为一系列单参数函数链式调用的技术,依赖闭包保存中间参数 。
示例:
function add(x) {
return function(y) {
return x + y;
};
}
add(2)(3); // 5
应用:参数复用、延迟执行、函数组合 。
作用:通过闭包生成具有独立状态的函数实例。例如生成独立的计数器:
function createCounter() {
let count = 0;
return function() {
return ++count;
};
}
const counter1 = createCounter(); // 独立作用域
场景:封装私有变量、实现模块化 。
事件回调:在闭包中使用 async/await
处理异步逻辑,避免全局变量污染 。
button.addEventListener(‘click’, () => {
(async () => {
const data = await fetchData();
console.log(data);
})();
});
定时器:闭包保存定时器状态,结合 async/await
控制执行流程 。
null
)。闭包是 JavaScript 的核心概念,与异步编程(Promise/async/await)、函数式编程(柯里化、工厂函数)紧密相关。理解闭包的作用域机制、内存管理,以及与其他特性的结合方式,是应对面试和实际开发的关键。
async/await 是 JavaScript 中处理异步操作的语法糖,其底层实现基于 Promise 和 Generator(生成器) 的协同机制。通过分析资料中的代码转换、设计原理和规范定义,其核心实现逻辑可拆解如下:
Promise 的基础作用
async/await 的异步控制完全依赖于 Promise 的链式调用。每个 await
表达式本质上会创建一个 Promise,并将后续代码包装到 .then()
中等待执行。例如:
async function foo() {
const result = await somePromise; // 等价于 somePromise.then(result => {...})
}
这种设计使得异步操作的 状态管理 和 错误传播 能够通过 Promise 链式结构实现。
Generator 的流程控制
Generator 函数通过 yield
关键字暂停执行,并通过迭代器(Iterator)手动恢复。async/await 利用这一特性,将异步代码的 暂停-恢复机制 转化为生成器函数的 yield
操作。例如,以下代码:
async function a() {
const res = await asyncTask();
}
会被 Babel 转换为使用 Generator 的代码:
function a() {
return __awaiter(this, void 0, void 0, function* () {
const res = yield asyncTask();
});
}
这里的 yield
替代了 await
,而 __awaiter
函数负责管理生成器的迭代。
通过 Babel/TypeScript 等工具的代码转换,async/await 的实现可拆解为以下步骤:
生成器函数包装
async 函数被转换为生成器函数,await
被替换为 yield
。例如:
// 原始代码
async function fetchData() {
const data = await fetch(url);
return data;
}
// 转换后代码(简化)
function fetchData() {
return __awaiter(this, function* () {
const data = yield fetch(url);
return data;
});
}
执行器函数(如 __awaiter
)的作用
执行器负责驱动生成器的迭代,并处理 Promise 的链式调用。其核心逻辑如下:
将生成器的每个 yield
值包装为 Promise。
通过 generator.next(value)
将 Promise 的结果传递回生成器。
捕获错误并通过 generator.throw(error)
抛出异常。
function __awaiter(generator) {
return new Promise((resolve, reject) => {
function step(result) {
if (result.done) {
resolve(result.value);
} else {
Promise.resolve(result.value).then(
value => step(generator.next(value)), // 传递结果并继续迭代
error => step(generator.throw(error)) // 抛出错误
);
}
}
step(generator.next());
});
}
此过程实现了 自动迭代 和 错误冒泡,使代码看似同步执行。
微任务队列的调度
await
后的代码会被包装为微任务(Microtask),在 Promise 解决后加入微任务队列。例如:
async function demo() {
console.log(1);
await Promise.resolve();
console.log(2); // 相当于 Promise.resolve().then(() => console.log(2))
}
demo();
console.log(3);
// 输出顺序:1 → 3 → 2
这种机制确保了异步代码的执行不会阻塞主线程。
协程(Coroutine)模型的实现
async/await 通过生成器和 Promise 模拟了协程的 挂起-恢复 行为:
await
处暂停生成器,释放主线程。try/catch 的转换
async 函数中的 try/catch
会被转换为 Promise 的 .catch()
链。例如:
async function foo() {
try {
await somePromise();
} catch (err) {
handleError(err);
}
}
转换后逻辑:
function* foo() {
try {
const result = yield somePromise();
} catch (err) {
handleError(err);
}
}
执行器在生成器抛出错误时触发 reject
。
未捕获异常的传播
若未使用 try/catch
,错误会通过 Promise 链冒泡到顶层,触发 unhandledrejection
事件。
生成器与 Promise 的开销
async/await 相比原生 Promise 链会引入额外开销(如生成器对象的创建),但在现代引擎中差异可忽略。
并发的实现方式
需显式使用 Promise.all()
实现并行,避免顺序等待:
async function parallel() {
const [a, b] = await Promise.all([task1(), task2()]); // 并行执行
}
若直接顺序 await
,会导致任务串行执行。
层级
实现机制
作用
语法层
async
/await
关键字
提供同步代码风格的异步写法
转换层
Babel/TypeScript 代码降级
将 async/await 转为 Generator + Promise
运行时层
生成器迭代器 + Promise 链
管理暂停/恢复、错误传播
事件循环层
微任务队列调度
确保异步代码非阻塞执行
通过多层抽象,async/await 将复杂的异步流程控制简化为直观的同步式代码,同时保持与 Promise 的完全兼容性。