【问题标题】:Updating UI With ASYNC Pipe and Returned Observable<{}>使用 ASYNC 管道和返回的 Observable<{}> 更新 UI
【发布时间】:2019-07-27 11:06:58
【问题描述】:

我很困惑,这可能是我在学习 rxJS 和 Observables 时一直采用的方法。

前言

我们的应用程序使用 Angular 连接到我们的公共 API 层 (C#)。从我的 ASYNC 调用返回的对象类型是 Observable。该流被传递给循环遍历项目的子组件。同样的流还允许用户添加 NoteDto 类型的新笔记或编辑笔记。理想情况下,当这些操作完成后,便笺列表将反映更新后的更改,而无需再次调用相同的服务调用来获取便笺。

代码

[notes.component.html]

<div *ngIf="(notes$ | async)?.items as notes; else loading">
    <note-card [noteData]="notes" (noteClick)="editNote($event)"></note-card>
</div>
<ng-template #loading>
    <div class="notes__container">
        <div class="note-card">
            <div class="note-card__primary-action">
                <div class="note-card__head">
                    <h2 class="note-card__title note-card-typography--headline1 text-center">Loading...</h2>
                </div>
            </div>
        </div>
    </div>
</ng-template>

[notes.component.ts]

import ...

@Component({
    ...
})
export class NotesComponent extends AppComponentBase implements OnInit {
    constructor(
        ...
        private _noteService: NoteServiceServiceProxy
    ) {
        super(injector);
    }

    public notes$: Observable<ListResultDtoOfNoteDto>;
    public userId: number;
    ...

    ngOnInit() {
        ...
        this.getNotes();
        ...
    }

    getNotes(): void {
        /*
            Binding to ASYNC pipe; which doesn't need a subscription since it is automatic?
            Returns type: Observable<ListResultDtoOfNoteDto> which is an array of NoteDto
        */
        this.notes$ = this._noteService.getUserNotes(this.userId, null);
        ...
    }
    ...

    public saveNote(note: NoteDto, mode: string) {
        if (mode === 'new') {
            this._noteService.addNote(note).subscribe(() => {
                this.cleanUp();
                this.getNotes();
                this.notify.info(this.l('SavedNoteSuccessfully'));
            });
        } 
        ...
    }
}

在子级中减去 clickEvent 的所有功能都发生在父级中。它会加载一个表单(反应式表单方法),该表单可以记录新笔记并保存或编辑旧笔记以进行更新。

我的问题

我只是想要一种方法来保存笔记并更新列表,而无需在添加新笔记时在订阅中再次调用 this.getNotes()。

(如果需要,我可以提供更多详细信息!)

编辑:目前忘记显示保存方法

【问题讨论】:

  • 您的笔记服务是否包含直接的 api 调用?如果您不想再次调用 getNotes,则需要将数据存储在服务中并在 add 调用完成后更新该数据(通常使用 HTTP POST 创建对象,您将获取创建的对象,因此您可以将此对象添加到包含您的数据的服务中)。如果您的应用程序(许多组件)严重依赖此数据基础,则可能值得一试github.com/ngrx/store,否则您可以编写一个包含您的数据的单例服务。
  • 我这不是在我的 getNotes() 方法中的 this.notes$ = this._noteService.getUserNotes() 技术上完成的吗?另外,如果您查看我的 SaveNotes() 方法,我认为我没有正确使用 ASYNC,因为我再次调用 GetNotes() 并再次重铸该服务调用

标签: angular rxjs observable


【解决方案1】:

实现此目的的一种方法是在您的 NoteServiceServiceProxy 内部拥有一个私有 BehaviorSubject,它将始终包含最新的注释值。

喜欢: private _notes = new BehaviorSubject&lt;ListResultDtoOfNoteDto&gt;(null)

  • 并且您公开了一个仅供消费者订阅的功能。
  • 您的 API 调用只会使用响应更新主题
public getNotes(): Observable<ListResultDtoOfNoteDto> {
    return this._notes.asObservable();
}

public getNotesFromApi(args): {
    // Api request
    this.httpClient.get().pipe(tap(result) => this._notes.next(result))
    // etc...
}

那么你需要在你的组件中做的就是声明你的 observable 类似

notesData = this. _noteService.getNotes();

init 内只需向API 发出请求以获取注释,它会自动更新您的notesData,这应该通过async 管道输出订阅您的模板。

当您保存时,您只需在末尾添加一个concatMap,以便您的保存首先进行,然后您从您的 api 请求更新。

类似

    this._noteService.addNote(note).pipe(
        concatMap(() => this._noteService.getNotesFromApi()))
        .subscribe();

这将再次更新模板上的 notesData 变量。

我希望您了解此流程的工作原理,如果没有,请随时提问。

希望这会有所帮助!

【讨论】:

  • 因此 API 是用 C# 编写的,我们使用的是 ASP .NET Zero 产品,该产品具有将 C# 转换为自动生成的 JS (Angular) 作为服务的过程。因此,服务是预先生成的,并直接进入 API 调用。是否可以在notes.component.ts 中完成您答案的前1/2?该流程完全有意义,我只是无法修改自动生成的服务代理,因为将来的更改只会覆盖文件。
  • 是的,我的意思是,如果您有一些限制,那么您必须根据自己的喜好对其进行调整。我认为在您的场景中,组件内部的状态也可以完成这项工作。因为流动仍然存在,但分离不存在。
  • 在解决这个问题时,我修改了你的答案,并创建了一个类似对象的私有数据存储,我可以从中推送和拉取数据并绑定回我们创建的可观察对象,该可观察对象是从公共变量中提取的作为异步对象。现在一切都运行得非常好,我不必再次手动点击 API 来刷新组件。谢谢!
猜你喜欢
  • 2021-01-26
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2021-05-24
  • 2017-03-12
  • 1970-01-01
  • 2021-12-06
相关资源
最近更新 更多