
异步编程【免费下载链接】qA promise library for JavaScript项目地址https://gitcode.com/gh_mirrors/q/q点击查看免费下载Q 是 JavaScript 早期的 Promise 库其 CHANGES.md 以版本为索引完整记录了从 0.0.1 到 1.5.1 的 API 演进、破坏性变更与底层实现调整。本文以该变更日志为骨架结合 q.js 源码与 spec/q-spec.js 测试梳理 Q 1.x 系列的核心能力Q.any、Q.Promise、长堆栈追踪、未处理拒绝追踪、noConflict与tap等并还原 0.9.x 时代的关键 API 清理与命名演变帮助你理解现代 Promise 之前的异步编程生态。版本总览与演进主线CHANGES.md 覆盖了 Q 从 0.0.1初始版本到 1.5.1当前仓库版本见 package.json 中version: 1.5.1的全部历史。整体演进可以划分为三条主线API 从实验走向稳定0.2.x 的post/invoke之争、0.8.x 的call/apply/bind体系、0.9.0 的大规模 API 清理最终收敛为 1.0 之后的稳定形态。能力不断向 ES6 Promise 靠拢Q.Promise构造器1.0.1、Q.any1.2.0、race、allSettled等组合方法逐步补齐。错误处理与调试体验持续增强长堆栈追踪0.8.5 起、未处理拒绝追踪0.9.4/1.3.0、done/nodeify等终止链式调用并暴露错误的手段。1.0.0 的发布说明很能说明项目定位这几乎就是 0.9 的重发布0.9 已进入温和的维护模式理应获得官方 1.0 的身份。野心勃勃的 2.0 即将到来但 0.9/1.0 已被广泛分发需要长期支持。见 CHANGES.md 1.0.0 小节。因此 1.x 系列本质上是 0.9 的稳定延续CHANGES.md 中 1.x 的条目也主要围绕新增 API 与缺陷修复。Q 1.x 系列稳定期的功能补全1.5.xQ.any错误信息与 finally 校验1.5.1有两处改动Q.any现在会在错误信息中注明Q.any 参与其中并且只包含最后一个被拒绝的 promise 的错误信息由 Ivan Etchart 贡献。查看 q.js 中any的onRejected处理当所有 promise 都被拒绝时会构造rejection.message Q cant get fulfillment value from any promise, all promises were rejected. Last error message: ...这正是 1.5.1 所描述的行为。在测试中避免使用domain.dispose为 Node.js 9 做准备由 Anna Henningsen 贡献对应测试代码在 spec/q-spec.js 中。1.5.0包含三项能力Q.any的错误信息取自最后一个被拒绝的 promise延续 1.5.1 的基础工作。如果传给finally即fin的回调不是函数现在会抛出异常由 grahamrhay 贡献。在源码中Promise.prototype.fin定义于 q.js 附近该校验保证了fin/finally的调用安全性。长堆栈追踪的重大改进现在可以在跨throw/rethrow 时构造长堆栈。此前长堆栈只能追踪单次异步跳转0.9.5 才支持完整历史追踪1.5.0 之后即使错误被重新抛出Q 也能把完整的异步历史拼接到error.stack上。1.4.x浏览器script场景的补强1.4.1修复了一个阻止 Q 作为 Firefox 附加组件script使用的问题。Q 现在可以在任何提供window或self全局变量的环境中运行并且优先使用window——因为附加组件的self是不可变的且与window不同。对应实现位于 q.js模块封装器先判断 CommonJS/RequireJS/SES再回退到window/self分支。1.4.0增加了noConflict支持由 jahnjw 贡献用于script场景下释放全局Q名称// 在 script 标签中使用时 // 保存之前的全局 Q然后挂载新的 Q var previousQ global.Q; global.Q definition(); global.Q.noConflict function () { global.Q previousQ; return this; };这段逻辑在 q.js 中可以直接看到noConflict会把全局Q恢复为加载前的值并返回当前的 Q 对象可通过return this得到引用继续使用。需要注意的是Q.noConflict只在 Q 作为全局变量使用时才有效q.js 中定义了静态版本的兜底在非全局环境下调用会抛出Q.noConflict only works when Q is used as a global错误。1.3.0Node.js 未处理/已处理拒绝追踪1.3.0 在 Node.js 中加入了未处理unhandled与已处理handled拒绝的追踪由 benjamingr 贡献。这其实是 0.9.4 引入的未处理拒绝 API的深化——现在 Q 会在拒绝被创建但从未被处理时通过process.emit(unhandledRejection, reason, promise)通知 Node.js 运行时并在拒绝稍后被处理时发出process.emit(rejectionHandled, ...)。源码实现位于 q.js 的UNHANDLED REJECTION TRACKING区块trackRejection(promise, reason)在Q.reject构造拒绝 promise 时被调用见 q.js把 promise 与 reason.stack 记入内部数组。untrackRejection(promise)在拒绝被then的 rejection handler 消费时被调用见 q.js。配套的公开 APIQ.getUnhandledReasons()返回当前未处理拒绝的堆栈快照副本见 q.js、Q.resetUnhandledRejections()清空追踪状态、Q.stopUnhandledRejectionTracking()关闭追踪。1.2.xQ.any诞生与 npm 打包瘦身1.2.0引入了Q.any(promisesArray)方法由 vergara 贡献返回一个 promise该 promise 以promisesArray中第一个被 fulfilled的 promise 的值作为 fulfillment 值如果数组中所有 promise 都被拒绝则返回被拒绝的 promise。这与all全部 fulfilled 才成功、第一个拒绝即失败和race第一个 settle 者胜出形成互补。从 q.js 的实现可以看到细节空数组输入时直接return Q.resolve()fulfilled 的空值不会拒绝内部用array_reduce遍历每个输入都挂上onFulfilled/onRejected/onProgress任何一个onFulfilled命中就deferred.resolve(result)定局只有pendingCount归零即全部被拒绝才构造错误并deferred.reject进度通知以{index, value}形式透传与Q.all的进度格式一致见 q.js。1.1.2改为在 package.json 中使用files白名单[LICENSE, q.js, queue.js]替代.npmignore黑名单从 npm 包里移除了多余文件由 anton-rudeshko 贡献。这与 CHANGES.md 中 0.8.6 引入.npmignore的改动形成呼应从黑名单排除到白名单包含的打包策略演进。1.1.xtap、Q_DEBUG与Q.nextTick可覆盖1.1.0是一系列实用增强Q_DEBUG1环境变量在 Node.js 中设置Q_DEBUG1即可全局开启长堆栈追踪。对应代码在 q.jsif (typeof process object process process.env process.env.Q_DEBUG) { Q.longStackSupport true; }tap方法promise 上的tap(callback)会在值经过时看一眼而不改变它适合插入日志、埋点等副作用操作。定义见 q.jsQ.tap与Promise.prototype.tap。用instanceof识别自有 promiseQ 现在通过instanceof Promise判断自己的 promise 实例而不是把所有 thenable 都当作 Q promise见 q.js 中Q(value)的分支逻辑。超时错误带code ETIMEDOUTPromise.prototype.timeout构造的错误对象会设置error.code ETIMEDOUT见 q.js方便程序化判断超时原因。Q.nextTick可被用户覆盖允许使用者替换 Q 内部的任务调度实现。同时移除了 Node.js 0.6/0.8 的持续集成原因是 npm 的^版本谓词运算符在传递依赖中无法在这些旧版本上使用。1.1.1修复了启动bootstrapping过程中的两处回归一处破坏了 WebWorker 支持另一处完全破坏了script用法issue #607。这与模块加载封装q.js的多种环境检测逻辑直接相关。1.0.xQ.Promise与 CSP 兼容1.0.1是 1.x 的重要里程碑Q.Promise构造器实现 ES6Promise构造器的常用用法new Q.Promise(function (resolve, reject, notify) {...})。源码中Q.Promise promiseq.js其实现位于function promise(resolver)q.js。CHANGES.md 同时说明Promise并没有一个合法的 promise 构造器真正的实现要等到 Q 2.0——即在 1.x 中该构造器与 ES6 语义仍有差异需注意使用前提。移除 promise inspector 的 console 兜底该方案已不再具备任何可靠性。CSP内容安全策略兼容修复了禁止eval的环境。Q 改用StopIteration全局变量来区分 SpiderMonkey 生成器与 ES6 生成器假设二者永不同时存在相关分支逻辑可见 q.js 的async实现。1.0.0本质是 0.9 的正式稳定化仅有少量细节调整例如浏览器中无论window.Touch是否定义都尝试输出调试信息移除promise.valueOf的弃用警告因为浏览器内部多种方式调用它无法区分需要迁移的用法。0.9.xAPI 清理与错误处理的分水岭0.9.x 是 Q 历史上最重要的演进期CHANGES.md 对这段历史的记录也最为详尽。0.9.0大规模 API 清理0.9.0 移除了一层被弃用/未文档化的方法使 Q 更贴近 Mark Miller 的 TC39 并发 strawman 提案。下表是 CHANGES.md 中的完整映射原文表格未做删减0.8.x 方法0.9 替代Q.refQcall、apply、bind(*)fcall/invoke、fapply/post、fbindncall、napply(*)nfcall/ninvoke、nfapply/npostenddoneputsetnodenbindnendnodeifyisResolvedisPendingdeferred.nodedeferred.makeNodeResolverMethod、senderdispatchersenddispatchview、viewInfo无*不鼓励使用thisp调用方法时请用post或invoke。配套的 API 变更还包括Q(value)现在是一个可调用的导出函数是resolve的别名q.js 中Q.resolve Qinvoke在所有形态下都是send的别名q.js 可看到Q.send/Q.mcall/Q.invoke的并排定义不带方法名的post行为等同于fapplydelete与set前身put不再有 fulfillment 值Q promise 不再被冻结因为冻结会损害 V8 性能新增thenReject作为thenResolve的对偶方法。错误处理方面长堆栈可以通过Q.stackJumpLimit 0关闭在 Node.js 中进程退出时若有未处理的拒绝会输出到控制台。内部协议Internals and Advanced内部 promise 接口改为dispatchPromise(resolve, op, operands)减少了参数切片内部操作码 put 改为 set、del 改为 delete新增Q.fulfill它与Q.resolve的区别在于不穿透 promise、也不强转其他系统的 promise——promise 本身就是 fulfillment 值仅建议在想用一个带有 then 函数但同时不是 promise 的对象去 fulfill 一个 promise时使用。0.9.50.9.7状态检视与生成器支持0.9.5引入了inspect——以{state: fulfilled | rejected | pending, value | reason}形式获取 promise 状态见 q.js 与 q.js 的 inspect 实现allSettled则把输入 promises 全部 settle 后的状态数组化。CHANGES.md 特别澄清了术语settled指 fulfilled 或 rejectedresolved指一个 deferred promise 被 resolve 到另一个 promise即把命运密封给后继 promise 的命运。同时长堆栈默认关闭需显式Q.longStackSupport true长堆栈可以追踪 promise 的完整异步历史而不仅是单次跳转引入spawn立即调用的异步生成器增加实验性的mapply、mcall、nmapply、nmcall方法调用同义词。0.9.6修复了inspect 实现之前的旧 Q promise 与兼容 Q promise 的识别问题并通过两条独立途径修复了无限异步强转循环所有makePromise返回的 promise 都实现inspect默认报告 unknown 状态then/when的实现迁移到then使强转职责集中在when。nextTick也被重构为无论请求多少个新 tick都在 Q 内部使用展开的微任务issue #316rkatic。0.9.7宣布q.min.js不再入库但仍由 Grunt 与 NPM 构建产出见 Gruntfile.js修复Q.async与 ES6 生成器的兼容问题修复nextTick影响 Safari 6.0.5 首次加载涉及 iframe的问题引入passByCopy、join、race控制台改为直接显示堆栈或错误消息而非Error对象消除包装方法以提升性能Q.all现在按 ES6 迭代的风格透传进度通知{value, index}。0.9.10.9.4API 打磨与未处理拒绝追踪0.9.1AMD 检测兼容 RequireJS 优化器的namespace选项issue #225修复valueOf的副作用——isFulfilled、isRejected、isPending不再意外触发外部代码issue #226。0.9.2timeout与delay现在会透传进度通知issues #229、#229 相关修复nbind真正绑定thisArgissue #232。0.9.3Q.timeout的错误支持自定义错误消息issue #270在 Node.js 0.10 中从process.nextTick切换到setImmediate修复调用栈爆栈问题issues #254、#259修复与浏览器中 Mocha 测试运行器的兼容Mocha 引入了没有nextTick的假process全局issue #267部分修复未处理拒绝检测的误报issue #252Q.promise在收到非函数参数时提前抛出异常。0.9.4isPromise与isPromiseAlike始终返回布尔值issue #284async支持 ES6 生成器issue #288清除 dispatch 方法中的重复拒绝issue #238引入未处理拒绝 APIissue #296domenicstopUnhandledRejectionTracking、getUnhandledReasons、resetUnhandledRejections——这正是 1.3.0 扩展的基础。0.8.x命名大调整与 Node 集成0.8.x 是命名与 API 形态剧烈变动的时期很多 0.9 时代的名字都源于此时。0.8.0移除enqueue用nextTick、def用master、spy用fin、wait用all(args).get(0)、join用all(args).spread(callback)delay同时接受(value, timeout)与(timeout)两种签名该双签名逻辑延续至今见 q.js新增spread新增defer().node()与node/ncallNode 风格回调适配。0.8.3promise 原型新增isFulfilled、isRejected、isResolved新增allResolved等待所有 promise 要么 fulfilled 要么 rejected不传播错误issue #53node导出改名nbindMethod改名sender浏览器控制台输出未处理错误的实时列表支持msSetImmediate/setImmediate作为浏览器端nextTick实验性别名finally对应fin、catch对应fail、try对应call、delete对应del。0.8.4promise.timeout的拒绝值从字符串改为Error对象消息中包含超时毫秒数CHANGES.md 明确标注这是一处未文档化、未指定公共行为的变更可能影响依赖字符串异常的用户新增deferred.makeNodeResolver()取代晦涩的deferred.node()新增实验性Q.promise(maker(resolve, reject))受 gozala 的流构造器模式与 Windows Metro Promise 构造器接口启发这就是Q.Promise的前身与Q.begin()。0.8.5初步支持长堆栈domenic新增fapply/fcall/fbind无 thisp 版本被拒绝的 promise 拥有exception属性引入 Jasmine 规范即本仓库的 spec/ 目录。0.8.6修复npost/ninvoke的thisp传递修复多种非常规拒绝原因的处理修复错误行为自定义 promise 的双重 resolve加速Q.all对已 resolve 的 promise 或标量值堆栈过滤支持资源合并issue #93为弃用方法添加警告添加.npmignore瘦身依赖包。0.8.9新增nend初步进度通知支持then(onFulfilled, onRejected, onProgress)、progress(onProgress)、deferred.notify(...)put/del返回被操作对象以支持链式调用。0.8.10done作为end的替代等价于then(f, r, p).end()Q.onerror可设置的错误陷阱用于获取未捕获错误的完整堆栈thenResolve快捷方式issue #108进度通知的透传与转换改进nend改名nodeifydeferred.resolve/deferred.reject不再有时返回deferred.promise修复spread在被拒绝 promise 上不调用拒绝处理器的缺陷。0.8.11新增nfcall/nfapply/nfbindncall/napply/nbind弃用长堆栈不再导致链式 promise 时内存线性增长issue #111拒绝处理器中检查error.stack现在能得到长堆栈issue #103修复Q.timeout在 promise 被拒绝时未清理定时器导致事件循环存活的缺陷issue #145新增q/queue模块无限 promise 队列构造器见 queue.js。0.8.12外部 promise 在Q.isFulfilled中被视为未 resolve使Q.all可以处理含外部 promise 的数组issue #154修复与 Promises/A 规范及测试套件的小型不一致issues #157、#158对应仓库中的 spec/aplus-adapter.js。0.7.x 及更早语源与根基更早的版本记录了许多至今仍在影响 Q 形态的决策0.7.0移除report与asapfin的 callback 不再接收任何参数enqueue改名nextTick修复MessageChannel用于nextTick的 bugshim 改为外部应用实验性view/viewInfo。0.6.0spy改名/别名finref以Q构造器形式导出新增async装饰器用yield来蹦床 promise即生成器支持的开端when、all变为可链式。0.5.x新增alljoin/wait重构为基于它全部在最早拒绝处拒绝fail、fin、spy加入 Q 与 promise 原型def改名master浏览器优先用MessageChannel做 next tickend结束 promise 链让传播的拒绝被抛出从而触发 Node 的uncaughtException与浏览器的onerror。0.4.xend不再返回 promise异常被消费后不再自动报告必须显式通过.end()或.then(null, Q.error)支持 RequireJSscript场景创建Q全局变量。0.3.0post恢复为 Tyler Closeref_sendAPI 的原始双参数签名第二个参数通常是参数数组新invoke提供可变参数调用Promise构造器改名makePromise术语细化isResolved改名isFulfilled新isResolved表示非 promise 或已 settled。0.2.xpost从(ref, name, args)改为可变参数(ref, name, ...args)0.2.0 破坏性变更thenable 采纳0.2.6使 Q 符合 Promises/A、B、Dpromise 变为鸭子类型promiseSend(op, resolved, ...)与valueOf0.2.5拒绝也鸭子类型化promiseRejected true且带reason新增q/queue、q/util模块。0.0.x0.1.x初始版本与asap的引入/移除0.1.0 因坏了大概坏在哲学上而移除。这段历史揭示了 Q 的深层设计哲学promise 不只是一个 API而是一套可跨库交换的协议鸭子类型、thenable 采纳、消息派发这为后来 ES6 Promise 的标准化提供了实践基础。用源码验证 1.x 核心 API 的当前形态以下能力在 q.js 中均可找到对应实现可作为阅读 CHANGES.md 时的对照索引CHANGES.md 提及的能力当前实现位置关键行为Q.anyq.js空数组直接 resolve首个 fulfilled 胜出全部拒绝才 reject错误信息含 Q cant get fulfillment value from any promiseQ.Promiseq.jsES6 风格(resolve, reject, notify)构造器异常自动转为拒绝未处理拒绝追踪q.jsunhandledRejection/rejectionHandled事件 getUnhandledReasons/resetUnhandledRejections/stopUnhandledRejectionTracking长堆栈支持q.jsQ.longStackSupport默认 falseQ_DEBUG1环境变量自动开启Q.stackJumpLimit 0可关闭tapq.js观察值经过而不改变timeoutq.js拒绝值带code: ETIMEDOUT拒绝/完成时清理定时器delayq.js双签名(value, ms)/(ms)拒绝立即透传Node 适配q.jsnfapply/nfcall/denodeify/nbind/ninvoke/npost/nodeifydeferred.makeNodeResolver生成器支持q.jsasync生成器 → promise 蹦床与spawn立即执行并done环境加载q.jsCommonJS / RequireJS / SES /script含noConflict多环境封装配套测试集中在 spec/q-spec.jsJasmine 行为规范与 spec/aplus-adapter.jsPromises/A 符合性适配器运行方式见 package.json 的 scriptsnpm testjasmine-node promises-aplus-tests jshint与npm run test-browseropener spec/q-spec.html。小结从 CHANGES.md 看 Q 的设计遗产纵览 CHANGES.mdQ 的演进有四个反复出现的主题至今仍具参考价值命名即文档resolve/fulfill/settle的术语区分0.9.5、isResolved→isFulfilled/isPending的细化0.9.0、0.3.0说明 API 命名需要精确承载语义。错误必须可见从end/done终止链、Q.onerror到未处理拒绝追踪0.9.4 → 1.3.0与长堆栈0.8.5 → 1.5.0 跨 rethrowQ 一直在解决异步错误被静默吞掉这一核心痛点。稳定与实验并存Q.Promise、Q.any等能力先以实验形态出现再逐步稳定同时大量实验性 APIview、sender、nend被及时清理。协议优于实现鸭子类型 promise、thenable 采纳、内部消息派发协议0.2.x0.9.x 一脉相承让 Q 能与 jQuery、Dojo、When.js、WinJS 等互操作README.md 的 Getting Started 一节有说明。对于现代开发者CHANGES.md 的价值在于它是理解ES6 原生 Promise 之前异步编程生态的第一手史料也是阅读 q.js 源码时的路线图——每一个 1.x API 都能在这份变更日志里找到它的来龙去脉。赞分享异步编程【免费下载链接】qA promise library for JavaScript项目地址https://gitcode.com/gh_mirrors/q/q点击查看免费下载相关推荐actix-web 版本演进全景解读从 CHANGES.md 看 Actix Web 4.x 核心 API 变迁与升级指南actix web 版本演进全景解读从 CHANGES.md 看 Actix Web 4.x 核心 API 变迁与升级指南 导读 本文以 actix web后端Web框架如何用ZMK开源键盘固件打造你的终极定制化机械键盘从入门到精通完整指南如何用ZMK开源键盘固件打造你的终极定制化机械键盘从入门到精通完整指南 厌倦了千篇一律的键盘布局想要一个真正懂你工作习惯的键盘吗ZMK开源键盘固件就是你的固件嵌入式智能硬件蓝牙GSYVideoPlayer 版本演进全解析从 1.x 到 13.x 的核心能力变迁与 API 实践指南GSYVideoPlayer 版本演进全解析从 1.x 到 13.x 的核心能力变迁与 API 实践指南 导读 本文以仓库 doc/UPDATE_VERSIO音视频移动开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考