|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +var ObservableBase = require('./observablebase'); |
| 4 | +var AbstractObserver = require('../observer/abstractobserver'); |
| 5 | +var Scheduler = require('../scheduler'); |
| 6 | +var BinaryDisposable = require('../binarydisposable'); |
| 7 | +var SingleAssignmentDisposable = require('../singleassignmentdisposable'); |
| 8 | +var ArgumentOutOfRangeError = require('../internal/errors').ArgumentOutOfRangeError; |
| 9 | +var inherits = require('inherits'); |
| 10 | + |
| 11 | +function TakeLastObserver(o, c, s, ss, ls) { |
| 12 | + this._o = o; |
| 13 | + this._c = c; |
| 14 | + this._s = s; |
| 15 | + this._ls = ls; |
| 16 | + this._ss = ss; |
| 17 | + this._q = []; |
| 18 | + AbstractObserver.call(this); |
| 19 | +} |
| 20 | + |
| 21 | +inherits(TakeLastObserver, AbstractObserver); |
| 22 | + |
| 23 | +TakeLastObserver.prototype.next = function (x) { |
| 24 | + this._q.push(x); |
| 25 | + this._q.length > this._c && this._q.shift(); |
| 26 | +}; |
| 27 | + |
| 28 | +TakeLastObserver.prototype.error = function (e) { |
| 29 | + this._o.onError(e); |
| 30 | +}; |
| 31 | + |
| 32 | +function loopRecursive(state, recurse) { |
| 33 | + if (state[1].length > 0) { |
| 34 | + state[0].onNext(state[1].shift()); |
| 35 | + recurse(state); |
| 36 | + } else { |
| 37 | + state[0].onCompleted(); |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +function loopLongRunning(state, cancel) { |
| 42 | + var o = state[0], q = state[1], n = q.length; |
| 43 | + while(!cancel.isDisposed) { |
| 44 | + if (n === 0) { |
| 45 | + o.onCompleted(); |
| 46 | + } else { |
| 47 | + o.onNext(q.shift()); |
| 48 | + } |
| 49 | + n--; |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +TakeLastObserver.prototype.completed = function () { |
| 54 | + this._ss.dispose(); |
| 55 | + if (this._s.scheduleLongRunning) { |
| 56 | + this._ls.setDisposable(this._s.scheduleLongRunning([this._o, this._q], loopLongRunning)); |
| 57 | + } else { |
| 58 | + this._ls.setDisposable(this._s.scheduleRecursive([this._o, this._q], loopRecursive)); |
| 59 | + } |
| 60 | +}; |
| 61 | + |
| 62 | +function TakeLastObservable(source, count, scheduler) { |
| 63 | + this.source = source; |
| 64 | + this.count = count; |
| 65 | + this.scheduler = scheduler; |
| 66 | + ObservableBase.call(this); |
| 67 | +} |
| 68 | + |
| 69 | +inherits(TakeLastObservable, ObservableBase); |
| 70 | + |
| 71 | +TakeLastObservable.prototype.subscribeCore = function (o) { |
| 72 | + var subscription = new SingleAssignmentDisposable(); |
| 73 | + var loopSubscription = new SingleAssignmentDisposable(); |
| 74 | + subscription.setDisposable(this.source.subscribe(new TakeLastObserver(o, this.count, this.scheduler, subscription, loopSubscription))); |
| 75 | + |
| 76 | + return new BinaryDisposable(subscription, loopSubscription); |
| 77 | +}; |
| 78 | + |
| 79 | +module.exports = function takeLast (source, count, scheduler) { |
| 80 | + if (count < 0) { throw new ArgumentOutOfRangeError(); } |
| 81 | + Scheduler.isScheduler(scheduler) || (scheduler = Scheduler.queue); |
| 82 | + return new TakeLastObservable(source, count, scheduler); |
| 83 | +}; |
0 commit comments