實(shí)戰(zhàn)指南)
后端【免費(fèi)下載鏈接】RxJSThe Reactive Extensions for JavaScript項(xiàng)目地址https://gitcode.com/gh_mirrors/rxj/RxJS點(diǎn)擊查看免費(fèi)下載Rx.Observable.jortSortUntil(other)是 RxJS v4Reactive Extensions for JavaScript中用于校驗(yàn)一個(gè) Observable 序列在另一序列觸發(fā)前是否始終保持有序的操作符它在other觸發(fā)或源序列自然結(jié)束時(shí)一次性輸出true已排序或false未排序。本文基于倉(cāng)庫(kù)文檔 doc/api/core/operators/jortsortuntil.md 展開結(jié)合 jortsortuntil.js 源碼 與 單元測(cè)試完整講解其 API、實(shí)現(xiàn)原理、運(yùn)行語義與使用限制幫助你掌握這一帶截止條件的排序檢測(cè)能力。jortSort 算法與它在 RxJS 中的定位jortSort 是一個(gè)反算法式的排序檢測(cè)思路詳見 jort.technology 的原始定義與其自己實(shí)現(xiàn)一個(gè)排序算法不如直接調(diào)用排序再比較排序前后是否一致——如果排序后的結(jié)果與原序列相同那么原序列本來就已經(jīng)有序。這個(gè)思路被包裝為 RxJS 的jortSort/jortSortUntil操作符屬于倉(cāng)庫(kù)的sorting擴(kuò)展構(gòu)建產(chǎn)物為 dist/rx.sorting.js對(duì)應(yīng)的聲明文件見 ts/rx.sorting.d.ts。在 RxJS v4 的上下文里序列就是 Observable。jortSortUntil的獨(dú)特之處在于它引入了一個(gè)截止條件源序列this持續(xù)發(fā)出元素操作符只負(fù)責(zé)把它們累積緩存起來當(dāng)參數(shù)other另一個(gè) Observable發(fā)出任何通知next 或 completed時(shí)jortSortUntil立即截?cái)嘣葱蛄袃?nèi)部基于takeUntil的語義隨后對(duì)已收集的全部元素做一次排序?qū)Ρ容敵鰡蝹€(gè)布爾值。由此它回答了這樣一個(gè)問題在截止信號(hào)到來之前我看到的這些輸入是否始終有序API 簽名與參數(shù)說明方法簽名observableProto.jortSortUntil function (other) { ... }參數(shù)otherObservable負(fù)責(zé)觸發(fā)終止的 Observable 序列。當(dāng)它發(fā)出通知時(shí)排序校驗(yàn)立刻進(jìn)行并結(jié)束。返回值Observableboolean一個(gè)只會(huì)輸出單個(gè)值的 Observable——true表示已收集的輸入序列有序false表示無序輸出該值后隨即Completed。TypeScript 聲明見 ts/rx.sorting.d.ts也印證了這一簽名jortSort(): Observableboolean; jortSortUntilTOther(other: TOther): Observableboolean;與jortSort()的關(guān)系倉(cāng)庫(kù)中的 jortsort.js 只有短短幾行jortSort本質(zhì)上是jortSortUntil的一個(gè)特例——用一個(gè)永不觸發(fā)的序列作為截止條件observableProto.jortSort function () { return this.jortSortUntil(observableNever()); };也就是說jortSort()沒有截止條件必須等源序列自然 Completed才能給出結(jié)論因此文檔特別注明 this is only for a sequence with an end即只適用于有限序列jortSortUntil(other)可以在源序列未完成時(shí)被other提前叫停并立即判定。源碼實(shí)現(xiàn)剖析一次調(diào)用背后的完整調(diào)用鏈核心實(shí)現(xiàn)位于 src/core/linq/observable/jortsortuntil.jsobservableProto.jortSortUntil定義在第 6–19 行完整代碼如下observableProto.jortSortUntil function (other) { var source this; return new AnonymousObservable(function (observer) { var arr []; return source.takeUntil(other).subscribe( arr.push.bind(arr), observer.onError.bind(observer), function () { var sorted arr.slice(0).sort(defaultSubComparer); observer.onNext(isEqual(arr, sorted)); observer.onCompleted(); }); }, source); };整個(gè)執(zhí)行流程可以拆解為四個(gè)階段1. 創(chuàng)建截止版源序列source.takeUntil(other)內(nèi)部調(diào)用takeUntil操作符當(dāng)other發(fā)出 next 或 completed 時(shí)源序列的訂閱會(huì)被立即終止。這意味著一旦other觸發(fā)jortSortUntil就只基于已經(jīng)到達(dá)的元素下結(jié)論后續(xù)元素即使有序或無序都不再納入判斷。2. 累積元素arr.push.bind(arr)在takeUntil的 next 回調(diào)中把每個(gè)到達(dá)的元素追加到數(shù)組arr。注意這是全量緩沖——在給出結(jié)論前操作符不會(huì)輸出任何中間結(jié)果元素越多內(nèi)存占用越大。3. 排序并對(duì)比arr.slice(0).sort(defaultSubComparer)isEqual序列完成自然完成或被other截?cái)鄷r(shí)執(zhí)行判定先arr.slice(0)拷貝一份原數(shù)組避免Array.prototype.sort原地修改污染原數(shù)據(jù)用defaultSubComparer排序。該比較器定義于 src/core/headers/coreheader.jsdefaultSubComparer Rx.helpers.defaultSubComparer function (x, y) { return x y ? 1 : (x y ? -1 : 0); };它按/做默認(rèn)升序比較因此jortSortUntil檢測(cè)的是非降序允許相等元素相鄰。最后調(diào)用Rx.internals.isEqual見 src/core/internal/isequal.js做深度相等比較。isEqual不是簡(jiǎn)單的而是支持對(duì)象深度遍歷的baseIsEqual/baseIsEqualDeep實(shí)現(xiàn)對(duì)普通值先做嚴(yán)格相等判斷再對(duì)對(duì)象遞歸比較因此元素為對(duì)象時(shí)也能按值比較內(nèi)容。4. 輸出結(jié)果observer.onNext(...)observer.onCompleted()比較結(jié)果為true排序前后一致原序列有序或false不一致輸出這個(gè)唯一的值后立即Completed。源序列的錯(cuò)誤則原樣透?jìng)鱫bserver.onError.bind(observer)不會(huì)進(jìn)行排序判定。完整可運(yùn)行示例以下是文檔jortsortuntil.md中的原始示例結(jié)合倉(cāng)庫(kù)結(jié)構(gòu)補(bǔ)齊了注釋與運(yùn)行說明。示例利用flatMap讓每個(gè)元素延遲 1 秒到達(dá)并用Rx.Observable.timer(3000)作為截止信號(hào)3 秒后無論源序列是否發(fā)完都立即判定。var just Rx.helpers.just; // —— 有序序列1,2,3,4 依序到達(dá)3 秒截止時(shí)恰好收滿 —— var source Rx.Observable.of(1,2,3,4) .flatMap(function (x) { return Rx.Observable.timer(1000).map(just(x)); }) .jortSortUntil(Rx.Observable.timer(3000)); var subscription source.subscribe( function (x) { console.log(Next: %s, x); }, function (e) { console.log(Error: %s, e); }, function ( ) { console.log(Completed); } ); // Next: true // Completed // —— 無序序列3,1,2,4 依序到達(dá) —— var source Rx.Observable.of(3,1,2,4) .flatMap(function (x) { return Rx.Observable.timer(1000).map(just(x)); }) .jortSortUntil(Rx.Observable.timer(3000)); var subscription source.subscribe( function (x) { console.log(Next: %s, x); }, function (e) { console.log(Error: %s, e); }, function ( ) { console.log(Completed); } ); // Next: false // Completed兩個(gè)示例的差異點(diǎn)只在輸入順序1,2,3,4已有序 →true3,1,2,4無序 →false。由于截止信號(hào)在 3 秒觸發(fā)而四個(gè)元素在 4 秒才全部發(fā)完所以兩次判定都在第 3 秒發(fā)生——這也直觀展示了截止條件可以提前結(jié)束校驗(yàn)的能力。行為語義與邊界情況結(jié)合單元測(cè)試 tests/observable/jortsortuntil.js 的 9 個(gè)用例可以把jortSortUntil的完整行為語義歸納如下場(chǎng)景源序列截止序列other結(jié)果never / never無元素、不完成不觸發(fā)無任何輸出assertEqual()空斷言empty / never無元素但 Completed不觸發(fā)Next: true隨即Completed空序列視為有序測(cè)試注釋中也留下了 Is empty really sorted or is it a headfake? 的疑問error / never途中拋錯(cuò)不觸發(fā)原樣透?jìng)麇e(cuò)誤error / empty途中拋錯(cuò)觸發(fā)仍透?jìng)麇e(cuò)誤錯(cuò)誤優(yōu)先于截止判定error pre-empted途中拋錯(cuò)在報(bào)錯(cuò)前觸發(fā)other先觸發(fā) → 直接按已收元素判定并Completed不再等待后續(xù)錯(cuò)誤pre-empted true有序元素未完成觸發(fā)Next: trueCompleted發(fā)生在other觸發(fā)時(shí)刻pre-empted false無序元素未完成觸發(fā)Next: falseCompletednot pre-empted true/false自然 Completed觸發(fā)晚于源完成在源序列 Completed 時(shí)刻判定結(jié)果同前關(guān)鍵結(jié)論誰先觸發(fā)誰裁決若源序列先自然完成判定發(fā)生在源完成時(shí)刻若other先觸發(fā)判定發(fā)生在other觸發(fā)時(shí)刻測(cè)試jortSortUntil pre-empted true中xs在 250 完成、ys在 245 觸發(fā)最終onNext(245, true)onCompleted(245)即證明判定發(fā)生在 245。錯(cuò)誤優(yōu)先源序列錯(cuò)誤會(huì)直接透?jìng)鱫ther無法掩蓋錯(cuò)誤除非other在錯(cuò)誤之前搶先觸發(fā)此時(shí)流已被截?cái)噱e(cuò)誤不再可見??招蛄幸暈橛行驔]有任何元素時(shí)排序前后均為空數(shù)組isEqual判定為相等輸出true。一次判定、單一結(jié)果輸出且只輸出一個(gè)布爾值后即結(jié)束屬于典型的一次性校驗(yàn)語義。使用前提與注意事項(xiàng)版本與文件依賴本文針對(duì)的是RxJS v4文檔標(biāo)題即注明 This is RxJS v 4。jortSortUntil屬于 sorting 擴(kuò)展發(fā)布在 dist/rx.sorting.js 中使用前需先引入前置依賴rx.js/rx.compat.js/rx.lite.js/rx.lite.compat.js之一對(duì)應(yīng)構(gòu)建入口與打包配置見 Gruntfile.js 與 index.js。較新的 RxJS 版本v5即 reactivex/rxjs 的現(xiàn)代重寫已不再提供該操作符遷移時(shí)需自行實(shí)現(xiàn)等價(jià)邏輯。全量緩沖的內(nèi)存代價(jià)從源碼可以看出判定前所有元素都累積在arr數(shù)組中。對(duì)無限或超長(zhǎng)序列jortSortUntil會(huì)持續(xù)占用內(nèi)存且other不觸發(fā)時(shí)永遠(yuǎn)不會(huì)給出結(jié)果——請(qǐng)務(wù)必搭配合理的截止信號(hào)使用。排序語義默認(rèn)按defaultSubComparer/升序比較即檢測(cè)非降序該比較器不支持自定義參數(shù)。若需要自定義比較規(guī)則不能直接通過本操作符完成。只對(duì)有限窗口生效因?yàn)榻Y(jié)論依賴排序后整體對(duì)比它本質(zhì)上要求被校驗(yàn)的片段是有限的由源完成或other觸發(fā)來界定無法像scan那樣逐元素增量判斷。小結(jié)Rx.Observable.jortSortUntil(other)以極簡(jiǎn)的 API 實(shí)現(xiàn)了在截止信號(hào)前校驗(yàn)輸入是否有序的能力內(nèi)部通過takeUntil(other)截?cái)嘣葱蛄邪训竭_(dá)元素累積成數(shù)組后用defaultSubComparer排序并用isEqual深度對(duì)比最終輸出單一布爾值。理解它的全量緩沖、默認(rèn)升序、錯(cuò)誤透?jìng)?、先到先裁決這四條核心語義你就能在 RxJS v4 中放心地把它用于窗口內(nèi)數(shù)據(jù)有序性的校驗(yàn)場(chǎng)景。更進(jìn)一步可以閱讀 jortsort.js無截止條件的變體、isequal.js深度比較實(shí)現(xiàn)以及 tests/observable/jortsortuntil.js全部邊界用例從源碼與測(cè)試兩個(gè)維度吃透這一操作符。贊分享后端【免費(fèi)下載鏈接】RxJSThe Reactive Extensions for JavaScript項(xiàng)目地址https://gitcode.com/gh_mirrors/rxj/RxJS點(diǎn)擊查看免費(fèi)下載相關(guān)推薦RxJS 4 bufferWithTime 操作符詳解基于時(shí)間窗口的流式批量緩沖RxJS 4 bufferWithTime 操作符詳解基于時(shí)間窗口的流式批量緩沖 bufferWithTime 是 RxJS 4Reactive Exten后端RxJS 4 的 average 操作符聚合平均值計(jì)算的源碼剖析與實(shí)戰(zhàn)指南RxJS 4 的 average 操作符聚合平均值計(jì)算的源碼剖析與實(shí)戰(zhàn)指南 Rx.Observable.prototype.average 是 RxJS 4后端RxJS操作符速查表按字母順序排列的參考RxJS操作符速查表按字母順序排列的參考 簡(jiǎn)介 RxJSReactive Extensions for JavaScript提供了豐富的操作符用于處理異后端創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考