尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

异步编程演进体系

异步编程演进体系 4.1 异步编程演进体系JavaScript 是单线程语言异步是为了解决耗时操作网络请求、文件读写、定时器阻塞主线程的问题异步方案经历了回调函数 → Promise → async/await1. 回调函数与回调地狱回调函数把一个函数作为参数传给另一个函数等到异步操作完成后再执行这个传入的函数。// 简单回调示例 function fetchData(callback) { setTimeout(() { callback(请求结果); }, 1000); } fetchData((res) { console.log(res); });回调地狱Callback Hell当多个异步操作存在先后依赖关系回调函数层层嵌套代码向右不断缩进可读性极差错误处理麻烦每层回调单独捕获异常难以复用、难以调试// 回调地狱示例 fetchA((resA) { fetchB(resA, (resB) { fetchC(resB, (resC) { console.log(resC); }); }); });核心痛点嵌套耦合异步流程无法用同步思维书写。2. Promise 核心体系Promise 是 ES6 引入的异步对象专门用来解决回调地狱把嵌套改为链式调用。Promise 三种状态状态不可逆pending等待中初始状态异步还没完成fulfilled已成功resolve()触发rejected已失败reject()触发状态一旦从 pending 变为 fulfilled / rejected就永久固定不能再改变。基础用法const p new Promise((resolve, reject) { // 异步任务 setTimeout(() { resolve(成功数据); // reject(错误信息); }, 1000); }); p.then((res) { // 成功回调 console.log(res); }).catch((err) { // 失败回调 console.error(err); }).finally(() { // 无论成功失败都会执行 });链式调用.then()会返回新的Promise对象因此可以持续链式替代回调嵌套fetchA() .then(resA fetchB(resA)) .then(resB fetchC(resB)) .then(resC console.log(resC)) .catch(err console.error(err));特点扁平代码不再嵌套整条链只需要一个 .catch() 捕获整条链上抛出的错误3. Promise 并发方法同时发起多个异步接收一个 Promise 数组返回新 Promise区别在于成功/失败的判定规则API触发时机返回值失败行为Promise.all([p1,p2,p3])全部fulfilled结果数组顺序和入参一致任一 promise reject直接reject短路Promise.allSettled([p1,p2,p3])所有promise都完成不管成功失败对象数组每个对象包含 status、value/reason永远不会 rejectPromise.race([p1,p2,p3])第一个完成无论成功失败第一个完成的结果谁最先结束就采用谁的状态Promise.any([p1,p2,p3])第一个fulfilled第一个成功的值全部失败才会 reject返回 AggregateError示例const p1 Promise.resolve(1); const p2 Promise.resolve(2); Promise.all([p1, p2]).then(res console.log(res)); // [1,2]业务场景all多个接口必须全部拿到数据再渲染如页面多个模块并行请求allSettled批量请求不管部分接口失败统一汇总所有结果race请求超时控制接口请求 vs 超时定时器竞赛any多服务冗余请求取第一个成功的接口返回4. async/await 语法糖与错误处理ES2017 引入Promise的语法糖底层仍然是 Promise只是让异步代码写法看上去像同步代码。基础规则async 修饰函数函数永远返回Promiseawait 只能写在 async 函数内部后面跟 Promise会暂停代码直到 Promise 完成async function getData() { const resA await fetchA(); const resB await fetchB(resA); const resC await fetchC(resB); console.log(resC); } getData();错误处理await遇到 reject 的 Promise会抛出异常两种捕获方案try/catch推荐async function getData() { try { const res await fetchA(); } catch (err) { console.error(请求出错, err); } }.catch() 直接跟在 await 的 Promise 后面const res await fetchA().catch(err {});注意await 串行执行如果想并行多个请求依然要用 Promise.all// 并行同时发起两个请求 async function parallel() { const [res1, res2] await Promise.all([fetchA(), fetchB()]); }演进小结回调函数最原始缺点是回调地狱、错误处理困难Promise解决嵌套提供链式调用 并发控制但是大量 then 依然有“链式阅读成本”async/awaitPromise 语法糖同步化写法可读性最好现代项目主流方案
返回列表