如何在 Angular 4 中推送到数组的 Observable? RxJS

Posted

技术标签:

【中文标题】如何在 Angular 4 中推送到数组的 Observable? RxJS【英文标题】:How to push to Observable of Array in Angular 4? RxJS 【发布时间】:2018-05-05 14:48:54 【问题描述】:

我的服务类有一个属性:

articles: Observable<Article[]>;

它由使用标准http.get().map() 解决方案的getArticles() 函数填充。

如何手动将新文章推送到此数组中;一个尚未持久化,因此不是 http get 的一部分?

我的场景是,您创建了一篇新文章,在保存之前,我希望 Article[] 数组将这个新文章推送到它,以便它显示在我的文章列表中。

此外,该服务在 2 个组件之间共享,如果组件 A 使用 ng OnInit() 使用该服务并将结果绑定到重复部分 *ngFor将从组件 B 更新服务数组同时更新组件 A 的 ngFor 部分中的结果? 还是我必须手动更新视图?

非常感谢, 西蒙

【问题讨论】:

只是确认一下,简单来说,如何直接修改这个 Observable 包含的数组? 这是我可以使用主题的地方吗? 【参考方案1】:

正如您在 cmets 中所说,我会使用主题。

保持articles 可观察而不是存储为数组的优点是http 需要时间,因此您可以订阅并等待结果。此外,这两个组件都会获得任何更新。

// Mock http
const http = 
  get: (url) => Rx.Observable.of(['article1', 'article2']) 


const articles = new Rx.Subject();

const fetch = () => 
  return http.get('myUrl').map(x => x).do(data => articles.next(data))


const add = (article) => 
  articles.take(1).subscribe(current => 
    current.push(article);
    articles.next(current);
  )


// Subscribe to 
articles.subscribe(console.log)

// Action
fetch().subscribe(
  add('article3')
)
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"&gt;&lt;/script&gt;

【讨论】:

由于 articles 是一个 observable,组件订阅它(在 javascript 中)或直接在带有 async 过滤器的模板上使用它。因此,由于它们是通过响应式管道连接的,因此每当主题更新时它们都会自动更新。 注意,您可以根据组件进行订阅的时间来改变所使用的主题的类型。对于在 ngOnInit 或模板中订阅的组件,普通的主题可能很好,但如果它们在应用流程中订阅较晚(比如 ComponentB 在辅助页面上),您可能需要使用 @ 987654326@ 存储最后一个值并为新订阅“重播”它。 我倾向于将Subject 视为组件插入的插座,但它没有存储空间。 ReplaySubject 是一个带有(可配置)存储的套接字,BehaviorSubject 有一个项目的存储空间,但可以采用初始值 - 用于为组件提供一些默认值之前获取已填充它价值。 将此标记为完整,因为我可以看到这是正确答案。但是,我在我的应用程序中工作时遇到问题。您愿意继续与我讨论以尝试解决我遇到的问题吗? 当然可以。你想怎么做 - 你可以添加到问题中吗?【参考方案2】:

您可能只想存储文章数组,而不是存储整个 observable,例如

articles: Article[]

fetch() 
    this.get(url).map(...).subscribe(articles => this.articles)

然后您可以使用标准数组操作方法来操作articles 列表。

如果你存储 observable,它会在你每次订阅它时重新运行 http 调用(或使用| async 渲染它),这绝对不是你想要的。

但为了完整起见:如果您确实有一个要添加项目的数组的 Observable,您可以在其上使用 map 运算符向其中添加指定的项目,例如

observable.map(previousArray =&gt; previousArray.concat(itemtToBeAdded))

【讨论】:

【参考方案3】:

来自 Angular 4 book ng-book

Subject<Array<String>> example =  new Subject<Array<String>>();


push(newvalue:String):void

  example.next((currentarray:String[]) : String[] => 
    return  currentarray.concat(newValue);
   )


example.next 中的内容是获取存储在 observable 中的当前数组值,并在其上连接一个新值并将新数组值发送给订阅者。这是一个 lambda 表达式。我认为这仅适用于主题 observables,因为它们保留存储在其方法 subject.getValue(); 中的最后一个值;

【讨论】:

以上是关于如何在 Angular 4 中推送到数组的 Observable? RxJS的主要内容,如果未能解决你的问题,请参考以下文章

在 Express 中推送到数组时插入参考文档

从 Vue.js 2 中的计算属性中推送到数组

如何在 React Router v5 中推送到历史记录?

如何在 React Router v5 中推送到历史记录?

如何在GCP发布/订阅中推送到多个端点?

如何从 gitlab CI 管道中推送到仓库?