在Angular/RXJS中向对象数组的Obervable添加/删除对象?

在Angular/RXJS中向对象数组的Obervable添加/删除对象?,angular,typescript,rxjs,observable,behaviorsubject,Angular,Typescript,Rxjs,Observable,Behaviorsubject,目标:将对象添加到现有可观察对象数组中。最后一步是在DOM上进行此反射 NewObject.ts: export class NewObject { name: string; title: string; } import { Observable } from 'rxjs'; import { Component, OnInit, Inject, EventEmitter } from '@angular/core'; import { NewObject } from 'obje

目标:将对象添加到现有可观察对象数组中。最后一步是在DOM上进行此反射

NewObject.ts

export class NewObject {
  name: string;
  title: string;
}
import { Observable } from 'rxjs';
import { Component, OnInit, Inject, EventEmitter } from '@angular/core';
import { NewObject } from 'objects';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {

  // Initializing the object array Observable from a service (step 1)
  readonly objects$: Observable<NewObject[]> = this.objectSvc.getAllObjects("objects").pipe(
    map(obj => obj.map(x => ({ name: x.name, title: alterString(x.title) }))),
    shareReplay(1)
  );

  constructor(
    private objectSvc: ObjectService
  ) { }

  ngOnInit() {

    somethingThatHappensToAdd = (response: any) => {
      let data = JSON.parse(response);
      data.forEach(x => {
        let obj: NewObject = { name: x.name, title: alterString(x.title) }

        // Here's where I'm trying to add the obj object into the already existing object array Observable
      });
    };

    somethingThatHappensToDelete = (response: any) => {
      let data = JSON.parse(response);
      data.forEach(x => {
        let obj: NewObject = { name: x.name, title: alterString(x.title) }

        // Here's where I'm trying to delete the obj object from the already existing object array Observable
      });
    };

  }
}
import { Injectable } from '@angular/core';
import { Observable, throwError, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { ClientApi, ApiException, NewObject } from '../client-api.service';

@Injectable({
  providedIn: 'root'
})
export class ObjectService {

  constructor(
    private clientApi: ClientApi
  ) { }

  getAllObjects(name: string): Observable<NewObject[]> {
    return this.clientApi.getAllObjects(name)
      .pipe(
        map((x) => x.result),
        catchError(err => {
          if (ApiException.isApiException(err)) {
            if (err.status === 404) {
              return of<NewObject[]>(undefined);
            }
          }
          return throwError(err);
        })
      );
  }
}
下面是
示例.component.ts

export class NewObject {
  name: string;
  title: string;
}
import { Observable } from 'rxjs';
import { Component, OnInit, Inject, EventEmitter } from '@angular/core';
import { NewObject } from 'objects';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {

  // Initializing the object array Observable from a service (step 1)
  readonly objects$: Observable<NewObject[]> = this.objectSvc.getAllObjects("objects").pipe(
    map(obj => obj.map(x => ({ name: x.name, title: alterString(x.title) }))),
    shareReplay(1)
  );

  constructor(
    private objectSvc: ObjectService
  ) { }

  ngOnInit() {

    somethingThatHappensToAdd = (response: any) => {
      let data = JSON.parse(response);
      data.forEach(x => {
        let obj: NewObject = { name: x.name, title: alterString(x.title) }

        // Here's where I'm trying to add the obj object into the already existing object array Observable
      });
    };

    somethingThatHappensToDelete = (response: any) => {
      let data = JSON.parse(response);
      data.forEach(x => {
        let obj: NewObject = { name: x.name, title: alterString(x.title) }

        // Here's where I'm trying to delete the obj object from the already existing object array Observable
      });
    };

  }
}
import { Injectable } from '@angular/core';
import { Observable, throwError, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { ClientApi, ApiException, NewObject } from '../client-api.service';

@Injectable({
  providedIn: 'root'
})
export class ObjectService {

  constructor(
    private clientApi: ClientApi
  ) { }

  getAllObjects(name: string): Observable<NewObject[]> {
    return this.clientApi.getAllObjects(name)
      .pipe(
        map((x) => x.result),
        catchError(err => {
          if (ApiException.isApiException(err)) {
            if (err.status === 404) {
              return of<NewObject[]>(undefined);
            }
          }
          return throwError(err);
        })
      );
  }
}
这是我的服务
对象.service.ts

export class NewObject {
  name: string;
  title: string;
}
import { Observable } from 'rxjs';
import { Component, OnInit, Inject, EventEmitter } from '@angular/core';
import { NewObject } from 'objects';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {

  // Initializing the object array Observable from a service (step 1)
  readonly objects$: Observable<NewObject[]> = this.objectSvc.getAllObjects("objects").pipe(
    map(obj => obj.map(x => ({ name: x.name, title: alterString(x.title) }))),
    shareReplay(1)
  );

  constructor(
    private objectSvc: ObjectService
  ) { }

  ngOnInit() {

    somethingThatHappensToAdd = (response: any) => {
      let data = JSON.parse(response);
      data.forEach(x => {
        let obj: NewObject = { name: x.name, title: alterString(x.title) }

        // Here's where I'm trying to add the obj object into the already existing object array Observable
      });
    };

    somethingThatHappensToDelete = (response: any) => {
      let data = JSON.parse(response);
      data.forEach(x => {
        let obj: NewObject = { name: x.name, title: alterString(x.title) }

        // Here's where I'm trying to delete the obj object from the already existing object array Observable
      });
    };

  }
}
import { Injectable } from '@angular/core';
import { Observable, throwError, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { ClientApi, ApiException, NewObject } from '../client-api.service';

@Injectable({
  providedIn: 'root'
})
export class ObjectService {

  constructor(
    private clientApi: ClientApi
  ) { }

  getAllObjects(name: string): Observable<NewObject[]> {
    return this.clientApi.getAllObjects(name)
      .pipe(
        map((x) => x.result),
        catchError(err => {
          if (ApiException.isApiException(err)) {
            if (err.status === 404) {
              return of<NewObject[]>(undefined);
            }
          }
          return throwError(err);
        })
      );
  }
}
从'@angular/core'导入{Injectable};
从“rxjs”导入{可观察的,投掷者,of};
从“rxjs/operators”导入{map,catchError};
从“../client api.service”导入{ClientApi,ApiException,NewObject};
@注射的({
providedIn:'根'
})
导出类对象服务{
建造师(
私人客户:客户
) { }
GetAllObject(名称:string):可观察{
返回此.clientApi.getAllObject(名称)
.烟斗(
映射((x)=>x.result),
catchError(err=>{
if(apieexception.isapieexception(err)){
如果(错误状态===404){
返回(未定义);
}
}
回程抛掷器(err);
})
);
}
}
JSON
中格式化响应后,我希望能够将
obj
对象插入到
objects$
Observable中,并使其反映在UI上


建议我使用
BehaviorSubject
元素来实现这一点。有人可以建议如何轻松地完成此操作吗?

您可以创建一个
行为子对象
来发出来自
某个事件的结果()
,并使用
组合测试()
将结果与来自服务的结果合并

objectsFromService$ = this.objectSvc.getAllObjects("objects").pipe(
    map(obj => obj.map(x => ({ name: x.name, title: alterString(x.title) })))
);

resultsArray = []
resultsSubject = new BehaviorSubject(this.resultsArray);
results$ = this.resultsSubject.asObservable()

readonly objects$: Observable<NewObject[]> = combineLatest(
    this.results$,
    this.objectsFromService$
).pipe(
   map(([results, objects]) => ([...results, ...objects])),
   shareReplay(1)
)


somethingThatHappens = (response: any) => {
      let data = JSON.parse(response);
      data.forEach(x => {
        let obj: NewObject = { name: x.name, title: alterString(x.title) }
        this.resultsArray.push(obj)          
      });
      this.resultsSubject.next(this.resultsArray)
};
objectsFromService$=this.objectSvc.getAllObject(“对象”).pipe(
map(obj=>obj.map(x=>({name:x.name,title:alterString(x.title)})))
);
结果数组=[]
结果主题=新行为主题(this.resultsArray);
结果$=this.resultsubject.asObservable()
只读对象$:可观察=组合相关测试(
此。结果$,
此.objectsFromService$
).烟斗(
映射(([结果,对象]=>([…结果,…对象]),
共享重播(1)
)
somethingthappens=(响应:any)=>{
让data=JSON.parse(响应);
data.forEach(x=>{
让obj:NewObject={name:x.name,title:alterString(x.title)}
this.resultsArray.push(obj)
});
this.resultsubject.next(this.resultsArray)
};
我创建了一个有效的stackblitz项目:


希望这能给你一个线索。

我认为哈伦的答案是好的()

如果您只更新此可观察对象一次(在init上),您可以执行以下简单操作:

export class ExampleComponent implements OnInit {

    let objects$: Observable<NewObject[]>;

    constructor(
        private objectSvc: ObjectService
    ) { }

    private initializeObservable() {
        return this.objectSvc.getAllObjects("objects").pipe(
            map(obj => obj.map(x => ({ name: x.name, title: alterString(x.title) }))),
            shareReplay(1)
        );
    }

    private getObservableWithNewValues() {
        const response = callService();
        let array = [];
        let data = JSON.parse(response);
        data.forEach(x => {
            let obj: NewObject = { name: x.name, title: alterString(x.title) }
            array.push(obj);
        });

        // This creates an observable of the array
        return of(array);
    }

    ngOnInit() {
        const initialObservable = this.initializeObservable();

        const anotherObservable = this.getObservableWithNewValues();

        this.objects$ = concat(initialObservable, anotherObservable);
    }
}
导出类ExampleComponent实现OnInit{
让对象$:可观察;
建造师(
私有objectSvc:ObjectService
) { }
private initializeObservable(){
返回此.objectSvc.getAllObject(“对象”).pipe(
map(obj=>obj.map(x=>({name:x.name,title:alterString(x.title)})),
共享重播(1)
);
}
私有getObservableWithNewValues(){
const response=callService();
让数组=[];
让data=JSON.parse(响应);
data.forEach(x=>{
让obj:NewObject={name:x.name,title:alterString(x.title)}
阵列推送(obj);
});
//这将创建阵列的可观察状态
返回(数组);
}
恩戈尼尼特(){
const initialObservable=this.initializeObservable();
const anotherObservable=this.getObservableWithNewValues();
this.objects$=concat(初始可观察,另一个可观察);
}
}
参考文献:


我找到了两种解决方案

解决方案1:

构造函数(私有myService:myService){
this.myService.getObjects().subscribe(x=>this.somethingthappenstoad(x));
}
结果数组=[]
结果主题=新行为主题(this.resultsArray);
只读对象$:可观察=组合相关测试(
此.resultsSubject,
).烟斗(
映射(([results])=>([…results]),
共享重播(1)
)
已加载的某些内容(数组值){
arrayOfValues.forEach(x=>{
此.resultsArray.push(x)
});
this.resultsubject.next(this.resultsArray)
};
删除(o:任何){
//这与仅访问This.resultsArray相同
让newArray:any[]=this.resultsSubject.getValue();
for(设i=newArray.length-1;i>=0;i--){
if(newArray[i]==o){
新阵列拼接(i,1);
}
}
this.resultsubject.next(newArray);
}
解决方案2:

deleteSubject=新主题();
addSubject=新主题();
objects$=this.myService.getObjects().pipe(
switchMap(x=>merge(
在(x)中,
this.deleteSubject.pipe(映射(y=>this.deleteAll(y,x)),
this.addSubject.pipe(映射(y=>{x.push(…y);返回x;}))
)),
共享重播(1)
);
构造函数(私有myService:myService){}
deleteAll(o:any,v:any[])){
对于(设i=v.length-1;i>=0;i--){
如果(v[i]==o){
v、 拼接(i,1);
}
}
返回v;
}

在向阵列添加其他项目时,这是一个极好的解决方案。如果您要删除项目,这会导致问题吗?很高兴它对您有效:)这不会导致任何问题类似于删除有点问题,您能提供任何帮助吗,我复制了stackblitz:当然。我明天一到我的电脑就会看一看你分享的代码。问题是您正试图删除来自服务的项目。为了删除它们,您需要将其从服务的
可观察的
源中删除,因为您要使用
async
管道。