首页 文章 精选 留言 我的

精选列表

搜索[AI编程],共10000篇文章
优秀的个人博客,低调大师

Snow 编程语言 v0.11.0 发布: 全面扩展系统调用

更新内容 新增功能 系统调用家族大扩展:覆盖文件系统、I/O、网络、进程、线程、并发、环境与时间等领域: 文件系统:CHDIR、GETCWD、MKDIR、RMDIR、READDIR、CHMOD、FCHMOD、UTIME、TRUNCATE/FTRUNCATE、RENAME、LINK/SYMLINK/READLINK、STAT/FSTAT。 I/O:OPEN、CLOSE、READ、WRITE、PIPE、DUP/DUP2、SEEK、SET_NONBLOCK、STDIN/STDOUT/STDERR 封装。 网络:socket/bind/listen/accept/connect/send/recv,以及 getsockopt/setsockopt/shutdown/getpeername/getsockname/getaddrinfo。 进程:EXIT、FORK、EXEC、WAIT、GETPID/GETPPID。 线程:THREAD_CREATE、THREAD_JOIN、THREAD_SLEEP。 并发:MUTEX/COND/SEM/RWLOCK 系列(new/lock/unlock/trylock/wait/signal/broadcast 等)。 环境与系统信息:GETENV/SETENV、NCPU、RANDOM_BYTES、ERRSTR/ERRNO、MEMINFO。 时间:CLOCK_GETTIME、NANOSLEEP、TIMEOFDAY、TICK_MS。 模块化 OS 层:新增并细化 os 模块为 io、fd、fs 子模块,统一系统调用入口与封装。 标准 I/O 统一:移除 PrintSyscall,全面切换为底层 STDOUT_WRITE;修正/统一 stdio 导入与调用。 注册表与工具集:新增/完善 FDTable、ProcessRegistry、ThreadRegistry、Mutex/Cond/Sem/RwlockRegistry、SocketRegistry、EpollRegistry;引入 EnvRegistry、SyscallUtils(统一 errno/errstr)、SelectorUtils(NIO 多路复用)。 性能和稳定性改进 升级至 graalvm-jdk-25+37.1 I/O 路径与多路复用:基于 SelectorUtils 的 NIO 多路复用与 SET_NONBLOCK 支持,降低阻塞与上下文切换成本。 FD 管理与调度:优化 FDTable 结构与查找性能,减少热路径开销。 执行链路简化:精简 SyscallFactory/SyscallCommand 与 CallGenerator 路径,统一错误返回与异常传播。 并发健壮性:完善锁/条件变量/信号量/RWLock 语义与边界条件处理,提升高并发场景稳定性。 开发者体验提升 一键运行:每个 Demo 均提供 .run.xml;同时更新运行配置与命名规范(含 Demo44–46 标准化)。 一致的错误语义:通过 SyscallUtils 统一 errno/errstr;日志与错误信息风格收敛,定位信息更明确。 工程化细节:更新 .gitignore(新增 demoDir、忽略 *.txt/output.txt);stdio 与 os 子模块导入一致化。 迁移提示:如仍使用 PrintSyscall,请迁移至 STDOUT_WRITE 封装。 Bug 修复 修复 Demo62/63 文件描述符未关闭与路径配置错误。 修复 close 栈平衡问题与字节数组编码异常。 修复多处 Demo 运行配置与边界输入下的异常处理不一致问题。 文档改进 术语与格式统一:清理冗余导入与代码片段,统一缩进/风格,提升可读性与检索性。 如遇到使用问题,欢迎及时 提交 Issue

优秀的个人博客,低调大师

JavaScript 异步编程指南:async/await 与 Promise 该怎么选?

在 JavaScript 开发中,异步操作就像家常便饭 —— 从调用后端 API 到读取本地文件,几乎无处不在。但很多开发者都会困惑:到底该用 Promise 的链式调用,还是 async/await 语法?其实答案很简单:没有绝对的好坏,只有场景的适配。 今天我们就用实际案例聊聊,这两种异步写法各自适合什么场景,以及如何在项目中混搭使用,让代码既高效又易读。 先搞懂:两者不是对立关系 很多人以为 async/await 是 Promise 的替代品,其实大错特错。async/await 本质是 Promise 的语法糖,它的底层依然是 Promise 实现。就像用for...of遍历数组比forEach更直观一样,async/await 让异步代码看起来更像同步代码。 先看个最简单的对比: // Promise写法 fetchData().then(data => { return processData(data); }).then(result => { console.log(result); }).catch(err => { console.error(err); }); // async/await写法 async function handleData() { try { const data = await fetchData(); const result = await processData(data); console.log(result); } catch (err) { console.error(err); } } 两者功能完全一致,但 async/await 的线性结构更符合人类的阅读习惯 —— 这也是它被广泛采用的核心原因。 优先用 async/await 的 3 种场景 什么时候用 async/await 更合适?记住一个原则:当异步操作需要按顺序执行,或者逻辑中有较多条件判断时。 1. 线性异步流程(一步接一步) 最典型的场景是依赖前一步结果的异步操作。比如先登录获取 token,再用 token 获取用户信息,最后用用户信息加载权限配置: // 用async/await,逻辑一目了然 async function initApp(username, password) { // 补充参数定义,避免未定义变量 try { const token = await login(username, password); const userInfo = await getUserInfo(token); // 依赖token const permissions = await getPermissions(userInfo.role); // 依赖userInfo renderApp(permissions); } catch (err) { showError(err); } } 如果用 Promise 链式调用写,虽然能实现,但嵌套越深(比如再加两步),可读性会明显下降。 2. 包含条件判断的异步逻辑 当异步流程中需要根据结果做分支判断时,async/await 的优势更明显。比如: async function checkAndUpdate() { const currentVersion = await getCurrentVersion(); // 同步的条件判断,自然融入异步流程 if (currentVersion < '2.0') { const updateInfo = await fetchUpdateInfo(); if (updateInfo && updateInfo.force) { // 增加可选链,避免updateInfo为undefined时报错 await showForceUpdateDialog(); } else { await showOptionalUpdateToast(); } } } 这段代码用 Promise 写会嵌套多层then,而 async/await 让同步逻辑和异步操作无缝衔接,就像写同步代码一样自然。 3. 需要中断执行的场景 有时候我们需要在异步流程中提前返回(比如参数无效时),async/await 的写法更直观: async function submitForm(data) { // 同步校验 if (!data?.email) { // 增加可选链,避免data为null/undefined时报错 showError('邮箱不能为空'); return; // 直接中断 } // 异步操作 try { const validateResult = await validateRemote(data); if (!validateResult.success) { showError(validateResult.message); return; // 校验失败,中断 } await submitData(data); showSuccess(); } catch (err) { handleError(err); } } 用 Promise 的话,需要在每个then里处理条件判断,代码会更零散。 优先用 Promise 的 3 种场景 虽然 async/await 很方便,但有些场景下,Promise 的原生 API(如Promise.all、Promise.race)更适合,甚至不可替代。 1. 并行执行多个异步操作 当多个异步任务互不依赖时,用Promise.all并行执行能大幅提高效率。比如同时加载列表数据和筛选条件: async function loadDashboard() { // 两个请求并行执行,总耗时是较慢那个的时间 const [products, categories] = await Promise.all([ fetchProducts(), fetchCategories() ]); renderProducts(products); renderFilters(categories); } 如果用await逐个调用,会变成串行执行(总耗时是两者之和),完全没必要: // 不推荐:串行执行,浪费时间 const products = await fetchProducts(); const categories = await fetchCategories(); // 等第一个完成才开始 2. 需要超时控制的异步操作 Promise.race可以实现 “谁先完成就用谁的结果”,非常适合超时控制。比如 “3 秒内没返回就显示加载失败”: // 封装一个带超时的异步函数 function withTimeout(promise, timeoutMs = 3000) { let timer; // 将timer提升到外部作用域 const timeoutPromise = new Promise((_, reject) => { timer = setTimeout(() => { reject(new Error('请求超时')); }, timeoutMs); }); return Promise.race([ promise, timeoutPromise ]).finally(() => clearTimeout(timer)); // 确保始终清除定时器 } // 使用 async function loadData() { try { const data = await withTimeout(fetchLargeData()); render(data); } catch (err) { showError(err.message); // 可能是超时错误 } } 这段代码用 async/await 无法实现,必须依赖 Promise 的race方法。 3. 处理动态数量的异步任务 当需要处理不确定数量的异步操作(比如批量上传多个文件),Promise.all是最佳选择: async function uploadFiles(files) { if (!files?.length) return; // 增加空值判断,避免空数组或undefined时执行无效操作 // 生成一个包含所有上传Promise的数组 const uploadPromises = files.map(file => { return uploadFile(file); // 每个文件的上传是异步操作 }); // 等待所有文件上传完成 const results = await Promise.all(uploadPromises); // 处理结果 const successCount = results.filter(r => r?.success).length; // 增加可选链容错 showMessage(`成功上传 ${successCount}/${files.length} 个文件`); } 这种动态场景下,Promise 的数组处理能力比 async/await 更高效。 混搭使用:发挥各自优势 实际开发中,两者往往结合使用效果最好。比如先并行获取基础数据,再串行处理后续逻辑: async function buildReport() { // 第一步:并行获取不相关的数据(提高效率) const [users, orders, products] = await Promise.all([ fetchUsers(), fetchOrders(), fetchProducts() ]); // 第二步:串行处理依赖关系的逻辑 const userStats = await calculateUserStats(users); const orderSummary = await generateOrderSummary(orders, userStats); // 依赖userStats const report = await compileReport(orderSummary, products); // 依赖前两者 return report; } 这段代码先用Promise.all并行请求,节省时间;再用 async/await 处理有依赖的串行逻辑,兼顾效率和可读性。 避坑指南:这些错误别犯 不要在循环中直接用 await 循环中用await会导致串行执行,如需并行,改用Promise.all: // 错误:串行执行,慢! for (const file of files) { await uploadFile(file); } // 正确:并行执行,快! await Promise.all(files.map(file => uploadFile(file))); 别忘了 try/catch async/await 中任何await的 Promise reject 都会触发异常,必须用try/catch捕获,否则会导致程序崩溃。 不要把 async 函数当同步函数用 async 函数永远返回 Promise,调用时必须用await或.then处理,直接调用会拿到 Promise 对象而非结果。 避免过度封装 简单的异步操作(比如单个请求)没必要包成 async 函数,直接返回 Promise 更简洁。 注意 Promise.all 的失败快速失败特性 Promise.all中任何一个 Promise reject 都会立即触发整个 Promise reject,如需等待所有结果(无论成功失败),可使用Promise.allSettled: // 等待所有任务完成,无论成功失败 // 文件上传场景优化 const results = await Promise.allSettled(uploadPromises); const failedFiles = results .filter(r => r.status === 'rejected') .map((r, i) => ({ file: files[i].name, error: r.reason })); 总结:一句话记住用法 用 async/await:处理线性依赖、包含条件判断、需要中断的异步流程; 用 Promise API:处理并行任务(all)、超时控制(race)、动态异步数组; 最佳实践:两者结合,并行任务用Promise.all,后续逻辑用 async/await 串联。 说到底,选择的核心是可读性和效率—— 哪种写法让团队成员更容易理解,哪种方式能让程序跑得更快,就用哪种。技术没有绝对的好坏,适合场景的才是最好的。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册