Home Manual Reference Source Test Repository

es6/operator/last.js

import { Subscriber } from '../Subscriber';
import { EmptyError } from '../util/EmptyError';
/* tslint:enable:max-line-length */
/**
 * 返回的 Observable 只发出由源 Observable 发出的最后一个值。它可以接收一个可选的 predicate 函数作为
 * 参数,如果传入 predicate 的话则发送的不是源 Observable 的最后一项,而是发出源 Observable 中
 * 满足 predicate 函数的最后一项。
 *
 * <img src="./img/last.png" width="100%">
 *
 * @throws {EmptyError} 如果 Observale 完成前还没有发出任何 `next` 通知的话,就会
 * 发送 EmptyError 给观察者的 `error` 回调函数。
 * @param {function} predicate - 任何由源 Observable 发出的项都必须满足的条件函数。
 * @return {Observable} 该 Observable 只发出源 Observable 中满足给定条件的最后一项,
 * 或者没有任何项满足条件时发出 NoSuchElementException 。
 * @throws - 如果在源 Observable 中没有匹配 predicate 函数的项,则抛出。
 * @method last
 * @owner Observable
 */
export function last(predicate, resultSelector, defaultValue) {
    return this.lift(new LastOperator(predicate, resultSelector, defaultValue, this));
}
class LastOperator {
    constructor(predicate, resultSelector, defaultValue, source) {
        this.predicate = predicate;
        this.resultSelector = resultSelector;
        this.defaultValue = defaultValue;
        this.source = source;
    }
    call(observer, source) {
        return source.subscribe(new LastSubscriber(observer, this.predicate, this.resultSelector, this.defaultValue, this.source));
    }
}
/**
 * We need this JSDoc comment for affecting ESDoc.
 * @ignore
 * @extends {Ignored}
 */
class LastSubscriber extends Subscriber {
    constructor(destination, predicate, resultSelector, defaultValue, source) {
        super(destination);
        this.predicate = predicate;
        this.resultSelector = resultSelector;
        this.defaultValue = defaultValue;
        this.source = source;
        this.hasValue = false;
        this.index = 0;
        if (typeof defaultValue !== 'undefined') {
            this.lastValue = defaultValue;
            this.hasValue = true;
        }
    }
    _next(value) {
        const index = this.index++;
        if (this.predicate) {
            this._tryPredicate(value, index);
        }
        else {
            if (this.resultSelector) {
                this._tryResultSelector(value, index);
                return;
            }
            this.lastValue = value;
            this.hasValue = true;
        }
    }
    _tryPredicate(value, index) {
        let result;
        try {
            result = this.predicate(value, index, this.source);
        }
        catch (err) {
            this.destination.error(err);
            return;
        }
        if (result) {
            if (this.resultSelector) {
                this._tryResultSelector(value, index);
                return;
            }
            this.lastValue = value;
            this.hasValue = true;
        }
    }
    _tryResultSelector(value, index) {
        let result;
        try {
            result = this.resultSelector(value, index);
        }
        catch (err) {
            this.destination.error(err);
            return;
        }
        this.lastValue = result;
        this.hasValue = true;
    }
    _complete() {
        const destination = this.destination;
        if (this.hasValue) {
            destination.next(this.lastValue);
            destination.complete();
        }
        else {
            destination.error(new EmptyError);
        }
    }
}
//# sourceMappingURL=last.js.map