【问题标题】:How to restart or refresh an Observable?如何重启或刷新 Observable?
【发布时间】:2015-12-20 21:46:10
【问题描述】:

我有一个 TypeScript/Angular 2 Observable,在我第一次调用它时就可以完美运行。但是,我有兴趣将多个订阅者附加到同一个可观察对象,并以某种方式刷新可观察对象和附加的订阅者。这是我得到的:

query(): Rx.Observable<any> {

return this.server.get('http://localhost/rawData.json').toRx().concatMap(
    result =>
        result.json().posts
    )
    .map((post: any) => {
        var refinedPost = new RefinedPost();
        refinedPost.Message = post.Message.toLowerCase();

        return refinedPost;

    }).toArray();

}

图片有一个刷新按钮,当按下该按钮时,它会重新执行这个 observable,并且任何连接到它的订阅者都会获得一组更新的数据。

我怎样才能做到这一点?

【问题讨论】:

    标签: javascript angular typescript rxjs


    【解决方案1】:

    我对 Angular2 和 Typescript 了解不多,但 typescript 是 javascript 的超集,我做了以下假设(如果我错了,请告诉我)应该使以下 javascript 代码工作:

    • server.get 返回一个承诺(或数组或 Rx.Observable)
    • postspost 的数组

    您需要从该按钮上的点击事件创建一个 observable,将该点击映射到您的 GET 请求,其余的应该或多或少如您所写。我无法测试它,但它应该遵循这些原则:

    // get the DOM id for the button
    var button = document.getElementById('#xxx');
    
    // create the observable of refined posts
    var query$ = 
        Rx.Observable.fromEvent(button, 'click')
            .flapMapLatest(function (ev) {
                         return this.server.get('http://localhost/rawData.json')
                       })
            .map(function (result){return result.json().posts})
            .map(function (posts) {
                    return posts.map(function(post){
                                       var refinedPost = new RefinedPost();
                                       refinedPost.Message = post.Message.toLowerCase();
                                       return refinedPost;
                               })
                 })
            .share()
    
    // subscribe to the query$. Its output is an array of refinedPost
    // All subscriptions will see the same data (hot source)
    var subscriber = query$.subscribe(function(refinedPosts){console.log(refinedPosts)})
    

    一些解释:

    1. 每次点击都会产生对server.get 的调用,该调用返回一个可观察兼容的类型(数组、承诺或可观察)。返回的 observable 被展平以从该调用中提取 result
    2. 因为用户可以点击很多次,每次点击都会产生它的数据流,而且我们只对最近一次点击的结果感兴趣(我在这里也做了另一个假设),我们使用操作符 flatMapLatest,它将执行flatMap 仅在最近一次点击生成的 observable 上
    3. 我们提取帖子posts 的数组并从中创建refinedPost 的数组。最后,每次点击都会产生一个refinedPost 的数组,我认为这就是你想要的
    4. 我们共享此 observable,因为您提到您将有多个订阅者,并且您希望所有订阅者看到相同的数据。

    让我知道我的假设是否正确以及这是否对您有用。

    另外我推荐你看看https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

    除了很好地提醒概念之外,它还解决了与您的非常相似的刷新服务器调用问题。

    【讨论】:

    • 感谢您的回答。这很好,但它假设我不确定:我直接捕获按钮点击。实际上,按钮单击处理程序与可观察的工作属于不同的类。我希望能够通过一个函数调用来启动 observable 的更新。 FWIW,我可以用一个主题做我想做的事,但我想知道是否有办法用“直接”来做到这一点
    • 是的,您可以将Rx.Observable.fromEvent(button, 'click') 替换为您的主题。有时您可以使用Rx.Observable.create 代替主题,将侦听器创建包装在其中,并返回一次性以删除侦听器-但没有看到您的代码,我不知道这是否可能。很高兴它起作用了。当没有更好的选择时使用主题没有任何问题,例如当您没有/不能在范围内拥有事件源时。顺便说一句,一些 SO 准则:如果答案对你有好处,你应该接受它。
    猜你喜欢
    • 2017-04-12
    • 1970-01-01
    • 2011-02-05
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    • 1970-01-01
    相关资源
    最近更新 更多