angular - 将普通变量转换为 Observable

标签 angular rxjs observable angular2-services

我的服务中有这个:

import { Injectable, EventEmitter } from '@angular/core'
import { Response } from '@angular/http'
import { Observable, ReplaySubject } from 'rxjs/Rx';
import { AppSettings, HttpClient } from './shared';
import _ from "lodash";

@Injectable()
export class UserService {

    private currentTruckTrailer: any;
    private trucksTrailers: any;
    public truckTrailerModified$: ReplaySubject<any>;

    constructor(private http: HttpClient) {
        this.truckTrailerModified$ = new ReplaySubject(1);

    }

    clearCache() {
        this.currentTruckTrailer = null;
        this.trucksTrailers = null;
    }

    login(username: string, password: string, clientID: number): Observable<any> {
        return this.http.post(`${AppSettings.API_ENDPOINT}/User/Login`, { username: username, password: password, clientID: clientID }).map((response: Response) => {
            return response.json();
        });
    }

    getTrailersAndTrucks(): Observable<any> {
        if (this.trucksTrailers) {
            return Observable.of(this.trucksTrailers);
        }
        else {
            return this.http.get(`${AppSettings.API_ENDPOINT}/User/GetTrailersAndTrucks`).map((response: Response) => {
                if (response.status == 200) {
                    this.trucksTrailers = response.json();
                    return this.trucksTrailers;
                }
                else {
                    return "FAILURE";
                }
            });
        }
    }

    saveTrailerAndTruck(truckID: string, trailerID: string): Observable<any> {
        return this.http.post(`${AppSettings.API_ENDPOINT}/User/SaveTrailerAndTruck`, { truckID: truckID, trailerID: trailerID }).map((response: Response) => {

            var truck = _.find(this.trucksTrailers.Trucks, function (item: any) {
                return item.ID == truckID;
            });

            var trailer = _.find(this.trucksTrailers.Trailers, function (item: any) {
                return item.ID == trailerID;
            });

            this.currentTruckTrailer = { Truck: truck, Trailer: trailer };

            this.truckTrailerModified$.next(this.currentTruckTrailer);
            return response.json();
        });
    }

    getCurrentTruckAndTrailer() {
        if (this.currentTruckTrailer) {
            return Observable.of(this.currentTruckTrailer);
        }
        else {
            return this.http.get(`${AppSettings.API_ENDPOINT}/User/GetCurrentTruckAndTrailer`).map((response: Response) => {
                if (response.status == 200) {
                    this.currentTruckTrailer = response.json();
                    return this.currentTruckTrailer;
                }
                else {
                    return "FAILURE";
                }
            });
        }
    }
}

上面的代码完美运行。我想要的是当我修改this.currentTruckTrailer时里面saveTrailerAndTruck订阅者应该自动更改他们的值。目前我正在使用公共(public) ReplaySubject truckTrailerModified$: ReplaySubject<any>;广播订阅。问题是我如何转动this.currentTruckTrailer到 Observable 中,以便听众可以直接订阅它。我需要在saveTrailerAndTruck内部进行哪些更改和getCurrentTruckAndTrailer .

最佳答案

您可以使用BehaviorSubject (documentation):

首先,你必须初始化它:

currentTruckTrailer:BehaviorSubject<any> = new behaviorSubject<any>();

当您想要存储数据的下一个值时,可以使用next():

this.currentTruckTrailer.next({ Truck: truck, Trailer: trailer });

当您订阅此 Observable 时,您将收到最后存储的值(如果存在),并且每次调用 next() 时都会调用您的订阅者。

编辑: 这是您服务中的示例实现。由于我不知道上下文以及您希望如何使用此服务,因此这可能不是您可以获得的最佳实现。此示例的目标是向您展示如何实现它。

import {Injectable} from '@angular/core'
import {Response} from '@angular/http'
import {Observable, BehaviorSubject} from 'rxjs/Rx';
import {AppSettings, HttpClient} from './shared';
import _ from 'lodash';

@Injectable()
export class UserService {

    private currentTruckTrailer: BehaviorSubject<any> = new BehaviorSubject<any>();
    private trucksTrailers: BehaviorSubject<any[]> = new BehaviorSubject<any[]>();

    constructor(private http: HttpClient) {
        //First of all, we initialize the currentTruckTrailer with a value coming from http.
        this.http.get(`${AppSettings.API_ENDPOINT}/User/GetCurrentTruckAndTrailer`)
            .subscribe((response: Response) => {
                this.currentTruckTrailer = new BehaviorSubject<any>(response.json());
            });

        //Same for truckTrailers.
        this.http.get(`${AppSettings.API_ENDPOINT}/User/GetTrailersAndTrucks`)
            .subscribe((response: Response) => {
                this.trucksTrailers = new BehaviorSubject<any[]>(response.json());
            });
    }

    login(username: string, password: string, clientID: number): Observable<any> {
        return this.http.post(`${AppSettings.API_ENDPOINT}/User/Login`, {
            username: username,
            password: password,
            clientID: clientID
        }).map((response: Response) => {
            return response.json();
        });
    }

    getTrailersAndTrucks(): Observable<any> {
        return this.trucksTrailers;
    }

    saveTrailerAndTruck(truckID: string, trailerID: string): Observable<any> {
        return this.http.post(`${AppSettings.API_ENDPOINT}/User/SaveTrailerAndTruck`, {
            truckID: truckID,
            trailerID: trailerID
        }).do(() => {

            const truck = _.find(this.trucksTrailers.Trucks, function (item: any) {
                return item.ID == truckID;
            });

            const trailer = _.find(this.trucksTrailers.Trailers, function (item: any) {
                return item.ID == trailerID;
            });

            this.currentTruckTrailer.next({Truck: truck, Trailer: trailer});
        }).map(response => {
            return response.json();
        });
    }

    getCurrentTruckAndTrailer(): Observable<any> {
        return this.currentTruckTrailer;
    }
}

关于angular - 将普通变量转换为 Observable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44065955/

相关文章:

node.js - Angular Quickstart 未能通过开箱即用的 karma 测试

angular - document.getElementsByTagName ('body' ) 的替代方案, Angular 为 2/5/6

Rxjs - 如何在通知 UI 错误的同时重试错误的可观察对象

F#:取消订阅 FSharp.Control.Reactive.Observable

html - 如何通过从列表中选择日期来显示信息

javascript - Angular2 数据表

javascript - 将深度嵌套的属性提取到唯一值数组中

javascript - Typescript:类型 'Audience' 无法分配给类型 'boolean'

android - AsyncTask 中的可观察/订阅者

javascript - knockoutjs 可观察对象绑定(bind)的可观察数组