免费自助建手机网站,手把手教你网上开店,美食网站设计模板,做网站选用什么域名比较好基础问答问#xff1a;async/await 的原理是什么#xff1f;答#xff1a;关键字本身就是 Promise 的语法糖#xff0c;依托于生成器函数 #xff08;Generator#xff09; 函数能力实现的。async 关键字标志这个函数为异步函数#xff0c;并且将返回结果封装为一个 Pro…基础问答问async/await 的原理是什么答关键字本身就是 Promise 的语法糖依托于生成器函数 Generator 函数能力实现的。async 关键字标志这个函数为异步函数并且将返回结果封装为一个 Promiseawait 则是暂停当前执行等待后续的异步操作完成后再恢复相当于 Generator 的 yield 。只是在 Generator 中需要手动调用 next() 触发执行 async 函数则内置该操作自动根据 await 的异步结果执行后续函数步骤。扩展延伸在上面提到了一个生成器函数Generator这个是 JavaScript 中的一种特殊函数可以暂停和恢复函数执行。在平时的开发中基本很少见到这个函数的使用不过面试的时候只要聊到了 async/await 内容90% 以上的概率会问到生成器函数。生成器函数使用 function* 语法定义他会返回一个生成器对象而不是和普通函数一样返回指定的结果如下示例// 定义一个Generator函数包含2个暂停点yield和1个返回值returnfunction* syncGenerator() {console.log(1. 函数开始执行);yield 第一个暂停结果; // 第一个暂停点返回值为第一个暂停结果console.log(2. 函数恢复执行);yield 第二个暂停结果; // 第二个暂停点返回值为第二个暂停结果console.log(3. 函数即将结束);return 最终返回结果; // 函数执行完毕返回最终结果}// 1. 调用Generator函数返回迭代器此时函数体未执行const genIterator syncGenerator();console.log(调用Generator后函数未执行, genIterator); // 输出Generator {suspended}// 2. 第一次调用next()执行到第一个yield暂停const result1 genIterator.next();console.log(第一次next()结果, result1);// 输出顺序// 1. 函数开始执行// 第一次next()结果{ value: 第一个暂停结果, done: false }donefalse表示未执行完毕// 3. 第二次调用next()从第一个yield恢复执行到第二个yield暂停const result2 genIterator.next();console.log(第二次next()结果, result2);// 输出顺序// 2. 函数恢复执行// 第二次next()结果{ value: 第二个暂停结果, done: false }// 4. 第三次调用next()从第二个yield恢复执行到return结束const result3 genIterator.next();console.log(第三次next()结果, result3);// 输出顺序// 3. 函数即将结束// 第三次next()结果{ value: 最终返回结果, done: true }donetrue表示执行完毕// 5. 第四次调用next()函数已结束后续调用均返回{ value: undefined, done: true }const result4 genIterator.next();console.log(第四次next()结果, result4); // 输出{ value: undefined, done: true }核心执行规则首次调用 Generator 函数仅返回迭代器函数体不执行每次调用 next ()函数从上次暂停位置继续执行直到遇到下一个yield或return返回结果结构next()返回的对象包含valueyield后的值或return的值和done布尔值标识是否执行完毕执行完毕后后续调用next()done始终为truevalue为undefined。面试之外你应该知道Generator 函数的核心价值在于“异步流程控制”即通过yield暂停执行异步操作等待异步结果返回后 调用 next() 恢复执行。这就是 async/await 的底层逻辑雏形。// 模拟接口请求异步函数返回Promisefunction fetchUser() {return new Promise((resolve) {setTimeout(() {resolve({ id: 1, name: 前端面试 });}, 1000);});}function fetchOrders(userId) {return new Promise((resolve) {setTimeout(() {resolve([{ orderId: 1001, goods: 面试指南 }]);}, 1000);});}// 定义异步Generator函数用yield暂停异步操作function* asyncGenerator() {console.log(开始请求用户信息);const user yield fetchUser(); // 暂停等待fetchUser的Promise完成console.log(用户信息请求完成, user);console.log(开始请求订单信息);const orders yield fetchOrders(user.id); // 暂停等待fetchOrders的Promise完成console.log(订单信息请求完成, orders);return { user, orders }; // 最终返回结果}// 手动执行异步Generator函数模拟async/await的自动执行器function runGenerator(genFn) {const genIterator genFn(); // 获取迭代器// 定义递归执行函数function handleNext(result) {// 若Generator执行完毕直接返回最终结果if (result.done) {return Promise.resolve(result.value);}// 若未执行完毕处理yield返回的Promise异步操作// result.value是yield后的值此处为fetchUser/fetchOrders返回的Promisereturn Promise.resolve(result.value).then((res) {// 异步操作完成后调用next(res)恢复执行将异步结果作为yield的返回值return handleNext(genIterator.next(res));}).catch((err) {// 捕获异步错误调用throw(err)将错误传入Generator函数return handleNext(genIterator.throw(err));});}// 启动第一次执行return handleNext(genIterator.next());}// 执行异步Generator函数runGenerator(asyncGenerator).then((finalResult) {console.log(所有异步操作完成最终结果, finalResult);}).catch((err) {console.log(异步操作出错, err);});async/await 本质是 Generator 自动执行器的语法糖二者核心逻辑可以一一对应上只是 async/await 的封装大大简化了使用流程特性 Generator 函数 async/await暂停 / 恢复标识 yield 关键字手动标记暂停点 await关键字自动标记暂停点执行控制 需手动调用迭代器的 next() 恢复执行 内置自动执行器无需手动控制异步结果处理 需手动用 Promise.resolve 等待异步结果 自动等待 await 后的 Promise 完成错误处理 需手动调用 iterator.throw(err) 传入错误 用 try/catch 自动捕获错误返回值 调用函数返回迭代器 调用函数返回 Promise语法简洁度 较繁琐需手动实现执行器 简洁无需关注执行细节面试追问生成器函数是怎么实现 async/await 的具体代码参考扩展延伸部分内容要代码描述。async/await 基础使用方式使用 Promise 不是更好为什么要用 async/await 关键字。async function waitRequest() {const resp await axios.request(https://hello.com)const data resp.data;return data、}可以使用Promise这个是根据使用场景来的async/await 只是将异步调用链转换成了同步代码阅读维护起来更方便。如封装一个等待延时通常使用的就是 await new Promise 来实现只是多数情况下 Promise 伴随着的是比较长的调用链带来阅读不便此时转换成同步代码就清晰易读了。如果 await 的表达式返回了 reject需要捕获吗要怎么捕获需要捕获否则会触发“Uncaught (in Promise) Error”中断代码执行这个类似于 throw error。需要使用 try...catch 捕获 await 表达式产生的错误及reject。