先给结论async/await可以理解为Generator Promise的语法糖。其中async函数本质上会返回一个Promiseawait本质上类似于对Promise的then早期实现思路上async/await可以看成是自动执行的 Generatoryield是 Generator 暂停执行的关键点一、先说yield是什么yield只能写在Generator 函数里。Generator 写法function* gen() { yield 1 yield 2 yield 3 }调用const g gen() console.log(g.next()) // { value: 1, done: false } console.log(g.next()) // { value: 2, done: false } console.log(g.next()) // { value: 3, done: false } console.log(g.next()) // { value: undefined, done: true }yield的作用yield表示“产出一个值并暂停函数执行”每次调用next()函数会从上一次暂停的位置继续往下执行。所以 Generator 的特点是函数可以暂停也可以恢复执行可以分段执行逻辑二、yield和普通函数有什么区别普通函数function fn() { console.log(1) console.log(2) console.log(3) } fn()会一次性执行到底。而 Generatorfunction* gen() { console.log(1) yield console.log(2) yield console.log(3) }只有调用next()才会一步步继续执行。三、为什么说async/await和yield有关系因为async/await的执行效果和Generator 自动执行器非常像。比如async function fn() { const a await Promise.resolve(1) const b await Promise.resolve(2) return a b }它很像下面这种 Generatorfunction* gen() { const a yield Promise.resolve(1) const b yield Promise.resolve(2) return a b }区别在于Generator 遇到yield会暂停但不会自动继续async/await遇到await后Promise resolve 之后会自动恢复执行所以可以说await和yield在“暂停函数执行”这件事上很像但await自带自动执行能力。四、async/await的原理1.async做了什么async声明的函数有两个核心特征特征一返回值一定是 Promiseasync function fn() { return 123 } fn().then(res { console.log(res) // 123 })相当于function fn() { return Promise.resolve(123) }特征二函数内部可以使用awaitawait会等待一个 Promise 完成。async function fn() { const res await Promise.resolve(100) console.log(res) }2.await做了什么await后面通常跟一个 Promiselet res await p它做的事可以理解为先暂停当前 async 函数等待 Promise 结果Promise resolve 后把结果返回给res再继续执行下面代码类似于p.then(res { // 继续往下执行 })所以await本质上是 Promise then 的同步写法表现。五、用 Generator 模拟 async/await这是面试里最常见的答法。例子先定义一个 Generatorfunction* gen() { const a yield Promise.resolve(1) const b yield Promise.resolve(2) return a b }这个 Generator 不会自己执行需要一个执行器。手写执行器function run(genFn) { const g genFn() function next(val) { const result g.next(val) if (result.done) { return Promise.resolve(result.value) } return Promise.resolve(result.value).then(data { return next(data) }) } return next() }调用run(gen).then(res { console.log(res) // 3 })执行过程gen()第一次执行const a yield Promise.resolve(1)返回{ value: Promise.resolve(1), done: false }执行器拿到这个 Promise 后Promise.resolve(result.value).then(data { next(data) })等 Promise 完成再把结果1传回去g.next(1)于是const a 1继续执行到下一个yield。如此反复直到结束。六、所以async/await本质像什么可以概括成async function fn() { const a await p1 const b await p2 return a b }近似于function fn() { return run(function* () { const a yield p1 const b yield p2 return a b }) }所以常说async/await Generator 的语法糖 自动执行器七、yield和await的区别这个很容易被问。1. 所在函数不同yield只能在function*里使用await只能在async function里使用2. 是否自动执行不同yield暂停后需要手动next()恢复await暂停后Promise 完成会自动恢复执行3. 语义不同yield更像“交出执行权”await更像“等待异步结果”4. 返回值体系不同Generator 返回的是迭代器对象async 函数返回的是 Promise对比代码Generatorfunction* gen() { const a yield Promise.resolve(1) console.log(a) } const g gen() g.next().value.then(res g.next(res))asyncasync function fn() { const a await Promise.resolve(1) console.log(a) } fn()很明显 async 用起来更简单。八、为什么 async/await 比 Generator 更好用因为 Generator 虽然也能写异步流程但有几个问题要手动调用next()要写执行器错误处理麻烦可读性不如await所以async/await就把这些细节封装掉了。你可以理解成Generator 提供“暂停/恢复”的能力Promise 提供“异步结果”而 async/await 把两者整合成了更自然的写法。九、async/await的简单实现思想如果面试官问“原理”你可以答这个简化版function myAsync(generatorFn) { return function () { const gen generatorFn.apply(this, arguments) return new Promise((resolve, reject) { function step(key, arg) { let res try { res gen[key](arg) } catch (err) { reject(err) return } const { value, done } res if (done) { resolve(value) } else { Promise.resolve(value).then( val step(next, val), err step(throw, err) ) } } step(next) }) } }它的思路就是调用 Generator 拿到迭代器执行next()如果遇到yield出来的 Promise就等待它完成完成后继续next(result)如果报错就调用throw最后包装成 Promise 返回这就是 async/await 的核心思想。十、错误处理也和 Promise 有关比如async function fn() { try { const a await Promise.reject(error) } catch (e) { console.log(e) } }底层可以理解成 Promise reject 后把错误抛回 async 函数内部。类似 Generator 执行器中的step(throw, err)所以 async/await 的异常机制本质上仍然是 Promise 的异常链。十一、面试标准回答你可以直接这么答async/await的底层原理可以理解为Generator Promise的语法糖。yield是 Generator 中用于暂停执行的关键字调用next()才能继续执行。await和yield很像都是让函数在某个位置暂停但await会在 Promise resolve 后自动恢复执行不需要手动next()。从实现思路上看async函数会被编译成一个返回 Promise 的函数函数内部通过类似 Generator 的方式分段执行再借助自动执行器把每一次await的结果传回去最终串联成同步写法的异步流程。十二、30 秒短答版了解。async/await本质上可以看成Generator Promise的语法糖。yield是 Generator 里让函数暂停执行的关键字需要手动调用next()恢复而await类似yield但它会等待 Promise 完成后自动继续执行所以用起来更像同步代码。底层实现思路就是通过执行器不断调用next()把 Promise 的结果传回 Generator。十三、一句话总结yield负责“暂停”Promise 负责“异步结果”async/await负责把它们封装成更易用的同步写法。
async原理了解吗?yield
先给结论async/await可以理解为Generator Promise的语法糖。其中async函数本质上会返回一个Promiseawait本质上类似于对Promise的then早期实现思路上async/await可以看成是自动执行的 Generatoryield是 Generator 暂停执行的关键点一、先说yield是什么yield只能写在Generator 函数里。Generator 写法function* gen() { yield 1 yield 2 yield 3 }调用const g gen() console.log(g.next()) // { value: 1, done: false } console.log(g.next()) // { value: 2, done: false } console.log(g.next()) // { value: 3, done: false } console.log(g.next()) // { value: undefined, done: true }yield的作用yield表示“产出一个值并暂停函数执行”每次调用next()函数会从上一次暂停的位置继续往下执行。所以 Generator 的特点是函数可以暂停也可以恢复执行可以分段执行逻辑二、yield和普通函数有什么区别普通函数function fn() { console.log(1) console.log(2) console.log(3) } fn()会一次性执行到底。而 Generatorfunction* gen() { console.log(1) yield console.log(2) yield console.log(3) }只有调用next()才会一步步继续执行。三、为什么说async/await和yield有关系因为async/await的执行效果和Generator 自动执行器非常像。比如async function fn() { const a await Promise.resolve(1) const b await Promise.resolve(2) return a b }它很像下面这种 Generatorfunction* gen() { const a yield Promise.resolve(1) const b yield Promise.resolve(2) return a b }区别在于Generator 遇到yield会暂停但不会自动继续async/await遇到await后Promise resolve 之后会自动恢复执行所以可以说await和yield在“暂停函数执行”这件事上很像但await自带自动执行能力。四、async/await的原理1.async做了什么async声明的函数有两个核心特征特征一返回值一定是 Promiseasync function fn() { return 123 } fn().then(res { console.log(res) // 123 })相当于function fn() { return Promise.resolve(123) }特征二函数内部可以使用awaitawait会等待一个 Promise 完成。async function fn() { const res await Promise.resolve(100) console.log(res) }2.await做了什么await后面通常跟一个 Promiselet res await p它做的事可以理解为先暂停当前 async 函数等待 Promise 结果Promise resolve 后把结果返回给res再继续执行下面代码类似于p.then(res { // 继续往下执行 })所以await本质上是 Promise then 的同步写法表现。五、用 Generator 模拟 async/await这是面试里最常见的答法。例子先定义一个 Generatorfunction* gen() { const a yield Promise.resolve(1) const b yield Promise.resolve(2) return a b }这个 Generator 不会自己执行需要一个执行器。手写执行器function run(genFn) { const g genFn() function next(val) { const result g.next(val) if (result.done) { return Promise.resolve(result.value) } return Promise.resolve(result.value).then(data { return next(data) }) } return next() }调用run(gen).then(res { console.log(res) // 3 })执行过程gen()第一次执行const a yield Promise.resolve(1)返回{ value: Promise.resolve(1), done: false }执行器拿到这个 Promise 后Promise.resolve(result.value).then(data { next(data) })等 Promise 完成再把结果1传回去g.next(1)于是const a 1继续执行到下一个yield。如此反复直到结束。六、所以async/await本质像什么可以概括成async function fn() { const a await p1 const b await p2 return a b }近似于function fn() { return run(function* () { const a yield p1 const b yield p2 return a b }) }所以常说async/await Generator 的语法糖 自动执行器七、yield和await的区别这个很容易被问。1. 所在函数不同yield只能在function*里使用await只能在async function里使用2. 是否自动执行不同yield暂停后需要手动next()恢复await暂停后Promise 完成会自动恢复执行3. 语义不同yield更像“交出执行权”await更像“等待异步结果”4. 返回值体系不同Generator 返回的是迭代器对象async 函数返回的是 Promise对比代码Generatorfunction* gen() { const a yield Promise.resolve(1) console.log(a) } const g gen() g.next().value.then(res g.next(res))asyncasync function fn() { const a await Promise.resolve(1) console.log(a) } fn()很明显 async 用起来更简单。八、为什么 async/await 比 Generator 更好用因为 Generator 虽然也能写异步流程但有几个问题要手动调用next()要写执行器错误处理麻烦可读性不如await所以async/await就把这些细节封装掉了。你可以理解成Generator 提供“暂停/恢复”的能力Promise 提供“异步结果”而 async/await 把两者整合成了更自然的写法。九、async/await的简单实现思想如果面试官问“原理”你可以答这个简化版function myAsync(generatorFn) { return function () { const gen generatorFn.apply(this, arguments) return new Promise((resolve, reject) { function step(key, arg) { let res try { res gen[key](arg) } catch (err) { reject(err) return } const { value, done } res if (done) { resolve(value) } else { Promise.resolve(value).then( val step(next, val), err step(throw, err) ) } } step(next) }) } }它的思路就是调用 Generator 拿到迭代器执行next()如果遇到yield出来的 Promise就等待它完成完成后继续next(result)如果报错就调用throw最后包装成 Promise 返回这就是 async/await 的核心思想。十、错误处理也和 Promise 有关比如async function fn() { try { const a await Promise.reject(error) } catch (e) { console.log(e) } }底层可以理解成 Promise reject 后把错误抛回 async 函数内部。类似 Generator 执行器中的step(throw, err)所以 async/await 的异常机制本质上仍然是 Promise 的异常链。十一、面试标准回答你可以直接这么答async/await的底层原理可以理解为Generator Promise的语法糖。yield是 Generator 中用于暂停执行的关键字调用next()才能继续执行。await和yield很像都是让函数在某个位置暂停但await会在 Promise resolve 后自动恢复执行不需要手动next()。从实现思路上看async函数会被编译成一个返回 Promise 的函数函数内部通过类似 Generator 的方式分段执行再借助自动执行器把每一次await的结果传回去最终串联成同步写法的异步流程。十二、30 秒短答版了解。async/await本质上可以看成Generator Promise的语法糖。yield是 Generator 里让函数暂停执行的关键字需要手动调用next()恢复而await类似yield但它会等待 Promise 完成后自动继续执行所以用起来更像同步代码。底层实现思路就是通过执行器不断调用next()把 Promise 的结果传回 Generator。十三、一句话总结yield负责“暂停”Promise 负责“异步结果”async/await负责把它们封装成更易用的同步写法。