使用Angular的async管道手动更新可观察对象。

huangapple go评论61阅读模式
英文:

Manually update observable using Angular's async pipe

问题

私有主题 = 新的 BehaviorSubject<Thing[]>([]);
公共 thingsData$: 可观察的<Thing[]>;

// 这段代码首次运行时将执行 HTTP GET
// 但如果有任何进一步的更改,下一个() 将更新模板中的异步管道。
public ngOnInit(): 无效 {
this.thingsData$ = this.subject.asObservable().pipe(
switchMap((things: Thing[]) => {
if (things.length) {
return of(things);
}
return this.thingService.getThings();
})
);
}

// 我不确定这最终是否是最佳方法
// 执行此部分,但它说明了使用 next() 的用法
public createThing(newThing: Thing, existingThings: Thing[]): 无效 {
this.thingService.saveThing(newThing)
.subscribe((savedThing: Thing) => {
subject.next(
existingThings.push(newThing);
);
});
}

英文:

I have an HTTP GET call that returns a list of things. I also have a POST that saves a new record and then returns the saved record. Using observables and the Angular async pipe, after POSTing a new record, I would like to merely append that new record to the list instead of doing a whole new GET to update the list.

private subject = new BehaviorSubject&lt;Thing[]&gt;([]);
public thingsData$: Observable&lt;Thing[]&gt;;

// The first run through this code will do the HTTP GET 
// but then if there are any further alterations, the 
// next() will update the async pipe in the template.
public ngOnInit(): void {
    this.thingsData$ = this.subject.asObservable().pipe(
        switchMap((things: Thing[]) =&gt; {
            if (things.length) {
                return of(things);
            }
            return this.thingService.getThings();
        })
    );
}

// I&#39;m not sure if this will ultimately be the best way
// to do this part but it illustrates the use of next()
public createThing(newThing: Thing, existingThings: Thing[]): void {
 this.thingService.saveThing(newThing)
   .subscribe((savedThing: Thing) =&gt; {
     subject.next(
       existingThings.push(newThing);
     );
   });
}

答案1

得分: 0

不需要使用switchMap,只需将行为主题命名为thingsData$,然后直接订阅服务。

this.thingService.getThings().subscribe(things => { this.thingsData$.next(things); });

当你使用可观察对象进行更新时,希望它发出一个新对象,不应该修改现有对象。使可观察对象发出新对象的标准方法是使用展开运算符。数组上的展开运算符用法如下 [...previousArray, newValue]。行为主题已经包含了现有的数据,所以可以这样更新:

public createThing(newThing: Thing): void {
  this.thingService.saveThing(newThing).subscribe((savedThing: Thing) => {
    this.thingsData$.next([...this.thingsData$.value, newThing]);
  });
}
英文:

There is no need for your switchMap, just call the behavior subject thingsData$ and subscribe straight to the service.

this.thingService.getThings().subscribe(things =&gt; { this.thingsData$.next(things); });

When you update with an observable you want it to emit a new object, you shouldn't mutate an existing object. The standard way of making an observable emit a new object is to use the spread operator. The spread operator on an array is used like [...previousArray, newValue]. The behavior subject already contains the exisiting things so you can update like.

public createThing(newThing: Thing): void {
  this.thingService.saveThing(newThing).subscribe((savedThing: Thing) =&gt; {
    this.thingsData$.next([...this.thingsData$.value, newThing]);
  }
}

答案2

得分: 0

以下是翻译好的部分:

  • You can create a single observable from two sources using merge.

    • 你可以使用 merge 从两个来源创建一个单一的可观察对象。
  • Let's call the two sources existingThings$ and createdThing$.

    • 让我们称这两个来源为 existingThings$createdThing$
  • We can use the scan operator to combine the emitted things from both sources into a single collection.

    • 我们可以使用 scan 运算符将来自两个来源的发射对象合并为一个单一集合。
  • Here's a working StackBlitz demo.

    • 这里有一个可运行的 StackBlitz 演示。
英文:

You can create a single observable from two sources using merge.

Let's call the two sources existingThings$ and createdThing$.

We can use the scan operator to combine the emitted things from both sources into a single collection.

  private existingThings$ = this.thingService.getThings();
  private createdThing$ = new Subject&lt;Thing&gt;();
  
  things$ = merge(this.existingThings$, this.createdThing$).pipe(
    scan((previous, current) =&gt; previous.concat(current), [] as Thing[])
  );
  
  createThing(newThing: Thing) {
    this.thingService.saveThing(newThing).subscribe(
      createdThing =&gt; this.createdThing$.next(createdThing)
    );
  }

Here's a working StackBlitz demo.

huangapple
  • 本文由 发表于 2023年2月10日 07:20:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75405477.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定