ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Cycle.js HTTP Driver 完全指南:请求流、响应元流与隔离语义

Cycle.js HTTP Driver 完全指南:请求流、响应元流与隔离语义 前端Web框架【免费下载链接】cyclejsA functional and reactive JavaScript framework for predictable code项目地址https://gitcode.com/gh_mirrors/cy/cyclejs点击查看免费下载导读cycle/http是 Cycle.js 生态中负责 HTTP 通信的官方驱动Driver它基于 superagent 为主体结合 http/src 目录下的源码与测试系统讲解驱动的安装接入、请求对象配置、响应消费方式、错误处理、并发策略与隔离语义帮助你写出数据流驱动的声明式网络请求代码。安装与基本接入在项目中使用前先通过 npm 安装驱动包npm install cycle/http仓库中cycle/http当前版本为15.4.0见 http/package.json其运行时依赖包括cycle/run、superagent、xstream并顺带引入most与rxjs以支持不同流库的适配。安装后即可在main函数中通过 drivers 对象注册驱动import xs from xstream; import {run} from cycle/run; import {makeHTTPDriver} from cycle/http; function main(sources) { // ... } const drivers { HTTP: makeHTTPDriver() } run(main, drivers);makeHTTPDriver是一个驱动工厂调用后返回驱动函数驱动函数接收一个请求流request$作为输入并返回一个 HTTP Source 对象详见 http/src/http-driver.ts 与 http/src/index.ts 的 JSDoc 说明。在 Cycle.js 约定中sink 命名HTTP对应 source 命名HTTP你可以在main中通过sources.HTTP访问 HTTP Source。发起请求最简单的用例驱动对请求流中每个事件的处理遵循要么是 URL 字符串要么是请求选项对象的约定见 normalizeRequestInput。最典型也最简单的方式是直接发送一个携带url的对象function main(sources) { let request$ xs.of({ url: http://localhost:8080/hello, // GET method by default category: hello, }); let response$ sources.HTTP .select(hello) .flatten(); let vdom$ response$ .map(res res.text) // We expect this to be Hello World .startWith(Loading...) .map(text div(.container, [ h1(text) ]) ); return { DOM: vdom$, HTTP: request$ }; }这段代码的要点方法默认值请求对象未指定method时默认为GET。在 preprocessReqOptions 中method会被规范化为小写且delete会转换为 superagent 使用的del。category分类键category是任意字符串用来在 HTTP Source 上按类别挑选响应。select(hello)内部正是通过res$.request.category category过滤响应元流的见 MainHTTPSource.select。响应是元流sources.HTTP.select()返回的是响应流的流$$记号因此必须调用.flatten()展平后才能拿到真正的响应对象res。响应对象结构res是 superagent 的响应对象包含status、text、body等标准字段可直接查阅 superagent 文档了解完整结构。驱动对请求流的校验从源码看驱动对非法输入有显式校验请求流若发射既非字符串也非对象的值会抛出错误Observable of requests given to HTTP Driver must emit either URL strings or objects with parameters.http-driver.ts请求对象缺少url字符串时抛出Please provide aurlproperty in the request options.http-driver.ts。这两条错误消息都被 http/test/browser/common.ts 的测试用例逐一断言可用于编写自定义驱动的行为参考。深入理解 Source 的 select 与 filter官方文档指出HTTP Source 并不是流而是提供两个查询方法的对象select(category?)返回响应元流传category时只保留request.category与之相等的响应流不传则返回全部MainHTTPSource.ts。filter(predicate)返回一个新的 HTTP Source其响应元流被谓词过滤谓词接收每个响应流上挂载的request对象MainHTTPSource.ts。一个完整的消费示例function main(source) { // The HTTP Source has properties: // - select(category) or select() // - filter(predicate) // Notice $$: it means this is a metastream, in other words, // a stream of streams. let httpResponse$$ source.HTTP.select(); httpResponse$$.addListener({ next: httpResponse$ { // Notice that httpResponse$$ emits httpResponse$. // The response stream has a special field attached to it: // request, which is the same object we emit in the sink stream. // This is useful for filtering: you can find the // httpResponse$ corresponding to a certain request. console.log(httpResponse$.request); }, error: () {}, complete: () {}, }); let httpResponse$ httpResponse$$.flatten(); // flattens the metastream // the reason why we need to flatten in this API is that you // should choose which concurrency strategy to use. // Normal xstream flatten() has limited concurrency of 1, meaning that // the previous request will be canceled once the next request to the // same resource occurs. // To have full concurrency (no cancelling), use flattenConcurrently() httpResponse$.addListener({ next: httpResponse { // httpResponse is the object we get as response from superagent. // Check the documentation in superagent to know the structure of // this object. console.log(httpResponse.status); // 200 }, error: (err) { // This is a network error console.error(err); }, complete: () {}, }); // The request stream is an object with property url and value // http://localhost:8080/ping emitted periodically, every second. let request$ xs.periodic(1000) .mapTo({ url: http://localhost:8080/ping, method: GET }); return { HTTP: request$ // HTTP driver expects the request$ as input }; }这里有几个关键机制值得展开1.request字段的挂载时机。每个响应流对象上被附加了只读的request属性其值就是驱动收到的原始请求选项。这发生在 requestInputToResponse$ 中先通过createResponse$(reqInput).remember()创建可记忆replay的响应流再用Object.defineProperty把规范化后的请求选项绑定到流对象上。测试 http/test/browser/common.ts 验证了response$.request.url与发起请求的 URL 一致。2. 为什么要 flatten。API 刻意让 select 返回元流目的是把并发策略的选择权交给你flatten()xstream 默认并发度为 1意味着后一个请求到来时会取消前一个针对同一资源尚未完成的请求——适用于以最新输入为准的场景如搜索框自动补全flattenConcurrently()提供全并发请求之间互不取消——适用于并行拉取多个独立资源。3. 内部创建响应流的原理。createResponse$ 用xs.create包裹 superagent 请求start时根据请求选项构造并发出请求end回调中区分错误与成功stop时调用request.abort()取消请求。因此当你取消对响应流的订阅时底层网络请求也会被中止。请求选项Request Options完整参考官方文档在 http/src/index.ts 的 JSDoc 中对请求对象属性做了权威说明同时 http/src/interfaces.ts 定义了RequestOptions类型。完整参数如下属性类型说明urlString远程资源路径必填否则驱动抛错methodStringHTTP 方法GET、POST、PUT 等默认getcategoryString可选任意键用于sources.http.select(category)挑选响应queryObjectGET/POST 的查询参数载荷sendObject | StringPOST 的请求体载荷headersObject自定义 HTTP 头acceptStringAccept 头typeString设置 Content-Type 的简写userString认证用户名passwordString认证密码fieldObject表单字段键/值为 Form 字段progressBoolean是否检测并发出进度事件到响应流attachArray上传资源数组每项含name、path、filenamewithCredentialsBoolean允许携带同源 Cookie默认falseagentObjectSSL 证书认证含cert与keyredirectsNumber跟随的重定向次数默认5lazyBoolean是否懒执行请求默认falseresponseTypeStringXHR 的responseType设置okFunction自定义成功判定回调接收响应对象返回true表示成功这些参数是如何被消费的optionsToSuperagent 是请求选项到 superagent 调用的映射层从实现上可以确认每个参数的底层行为withCredentials与redirects会被预处理withCredentials默认falseredirects只有在传入数字时才生效、否则默认5preprocessReqOptions方法名delete被转译为 superagent 的deltype、send、accept、query分别映射到 superagent 的同名链式方法agent.key/agent.cert被用于客户端 SSL 证书user与password必须同时为字符串才会调用auth()headers、field通过for...in逐个set到请求上attach数组按倒序遍历依次attach(name, path, filename)progress为true时驱动监听 superagent 的progress事件并把带request字段的进度响应发射到流中createResponse$。lazy 与 eager请求何时真正发出默认情况下lazy: false驱动是急切执行的只要请求流发射事件请求就会立即发出即使应用从未订阅对应的响应流。实现上requestInputToResponse$ 在!reqOptions.lazy时立刻向响应流挂一个空监听器来触发start。若设置lazy: true请求只会在你订阅该响应流时即调用.flatten()后真正消费时才发出。这对只在需要时拉取数据的场景很有用。错误处理响应流是流的流因此每个单独的响应流都可以独立捕获错误。官方文档给出的模式是对每个response$使用replaceError兜底再展平sources.HTTP .select(hello) .map((response$) response$.replaceError(() xs.of(errorObject)) ).flatten()原理在于response$上的error事件代表网络级错误连接失败、超时、4xx/5xx 等会中断该响应流replaceError把错误替换为携带错误对象的正常事件从而让下游的.flatten()合并后不会因单条响应失败而中断整体数据流更细粒度的成功/失败判定可用ok回调自定义(res) boolean决定哪些状态码视为成功。xstream 用户参考replaceError操作符RxJS 用户可对应使用catchcatchError操作符。真实项目中的多分类响应实践examples/intermediate/http-search-github/src/main.js 演示了category的实际价值同一个应用中同时存在GitHub 仓库搜索请求category: github和无关的 Google 请求category: google二者合并为同一请求流const searchRequest$ sources.DOM.select(.field).events(input) .compose(sources.Time.debounce(500)) .map(ev ev.target.value) .filter(query query.length 0) .map(q ({ url: https://api.github.com/search/repositories?q${encodeURI(q)}, category: github, })); const otherRequest$ sources.Time.periodic(1000).take(2) .mapTo({url: http://www.google.com, category: google}); const request$ xs.merge(searchRequest$, otherRequest$); // 只消费 github 类别的响应 const vtree$ sources.HTTP.select(github) .flatten() .map(res res.body.items) .startWith([]) .map(results div([/* ... */]));这正是select(category)的典型用途在请求流合并的前提下按类别精确挑选自己关心的响应避免无关响应干扰 UI 渲染。配合debounce(500)还能实现输入防抖减少无效请求。隔离语义Isolation SemanticsCycle HTTP 支持通过cycle/isolate包进行组件间隔离。给定isolate(Component, scope)中的scope隔离行为有两种当 scope 为null不隔离。子组件与父组件运行在同一上下文。父组件通过HTTPSource.select()能看到子组件产生的响应流子组件也能看到父组件产生的响应——即子组件可以看到并非自己发起的响应。当 scope 为字符串兄弟隔离siblings isolation。父组件的HTTPSource.select()能访问其所有子组件的 HTTP 响应但被兄弟隔离的子组件内部HTTPSource.select()无法访问其他同样被兄弟隔离的子组件产生的响应。每个隔离子组件只能看到自己命名空间内的响应。从源码看隔离机制依赖请求选项中的_namespace数组类型定义见 interfaces.tssink 侧isolateSink对子组件发出的每个请求把scope前插到_namespace头部字符串形式的请求会被规范化为{url, _namespace: [scope]}source 侧isolateSource先通过filter只保留_namespace与当前作用域链完全匹配的响应流arrayEqual 做逐项比较再以scope扩展命名空间。MainHTTPSource的构造函数持有_namespace数组初始为空[]filter返回的新 Source 会concat(scope)追加命名空间MainHTTPSource.ts。这种命名空间前缀匹配的设计恰好实现了文档描述的两种隔离语义null时直接返回原 Source 不做任何过滤字符串时按命名空间精确过滤。隔离相关的驱动形态从 most.ts 与 rxjs.ts 可以看出cycle/http的核心实现与流库解耦默认导出基于 xstream同时提供了 most 与 RxJS 的适配入口两种适配下的HTTPSource接口均保留filter、select、isolateSource、isolateSink四个方法只是流的类型分别替换为 most 的Stream与 RxJS 的Observable。测试 http/test/browser/common.ts 也验证了返回的 HTTPSource 自带isolateSource与isolateSink可供组合子组件时直接使用。浏览器支持与限制该驱动依赖 superagent而 superagent 明确不支持 IE 8因此cycle/http同样不支持 IE 8。驱动的测试覆盖 Node 与浏览器两端pnpm run test-node与pnpm run test-browser见 http/package.json浏览器端通过 karma 跑在真实浏览器环境中。小结cycle/http把 HTTP 通信完全纳入 Cycle.js 的响应式数据流模型请求是 sink 流响应是 source 元流。掌握三个核心即可上手实战请求侧请求流发射字符串或请求选项对象url必填method默认GET其余参数query、send、headers、auth、attach、progress、lazy、ok等逐一映射到 superagent 行为响应侧select(category)/filter(predicate)挑选响应元流按需选择flatten()串行取消或flattenConcurrently()全并发单条响应流可用replaceError独立兜底隔离通过cycle/isolate的scopenull或字符串控制组件间响应可见性底层由_namespace命名空间前缀匹配实现。如需更深入的使用案例可继续研读仓库内的 http 驱动源码、浏览器端测试 以及 http-search-github 示例。赞分享前端Web框架【免费下载链接】cyclejsA functional and reactive JavaScript framework for predictable code项目地址https://gitcode.com/gh_mirrors/cy/cyclejs点击查看免费下载相关推荐GeledgedbAI HTTP API 完全指南Embeddings 与 RAG 端点的请求、响应与 SSE 流式实战GeledgedbAI HTTP API 完全指南Embeddings 与 RAG 端点的请求、响应与 SSE 流式实战 本文是 Geledgedb内数据库图数据库关系型数据库OpCore-Simplify如何在3分钟内完成Hackintosh EFI配置OpCore Simplify如何在3分钟内完成Hackintosh EFI配置 传统Hackintosh配置需要数小时的手动调试而OpCore Simp开发工具CLISanic 流式处理完全指南请求流、响应流与文件流的实战与源码解析Sanic 流式处理完全指南请求流、响应流与文件流的实战与源码解析 流式处理Streaming是构建高并发、低内存 Web 应用的关键能力它让服务端在请后端Web框架上一篇5分钟掌握Windows风扇控制FanControl免费软件终极指南下一篇猫抓浏览器扩展一键嗅探下载网页视频资源的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表