RX 最佳实践:Select 有副作用还是使用订阅?

RX Best Practice: Select with side-effect or use subscribe?

我将事件(来自按钮的分页事件)转换为 IObservable 并从服务异步接收结果。

作为副作用,我必须更新子视图。我有两个解决方案:

  1. 选择中的副作用:

        //Converting events to a "stream" of search results.
        IObservable<SearchResult> resultsFromPageChange = Observable.FromEventPattern<EventArgs>(this,
            "PageChangedEvent")
            .Throttle(TimeSpan.FromMilliseconds(500))
            .Select(async ev =>
             {
                 var input = new SearchResultInput()
                 {
                     PageSize = PageSize,
                     PageIndex = PageIndex,
                     SearchOptions = _currentSearchOptions,
                     SearchText = SearchText.Value
                 };
                 var result = await GetPagedComponents(input);
                 //Side effect
                 ActivateAttributesView(result.Components.FirstOrDefault());
    
                 return result;
             }).Switch(); //flatten and take most recent.
    
  2. 在订阅中做副作用:

        //Converting events to a "stream" of search results.
        IObservable<SearchResult> resultsFromPageChange = Observable.FromEventPattern<EventArgs>(this,
            "PageChangedEvent")
            .Throttle(TimeSpan.FromMilliseconds(500))
            .Select(async ev =>
            {
                var input = new SearchResultInput()
                {
                    PageSize = PageSize,
                    PageIndex = PageIndex,
                    SearchOptions = _currentSearchOptions,
                    SearchText = SearchText.Value
                };
                return await GetPagedComponents(input);
            }).Switch(); //flatten and take most recent.
    
        //Do side effect in the subscribe
        resultsFromPageChange.Subscribe(x =>
        {
            if (x != null)
                ActivateAttributesView(x.Components.FirstOrDefault());
        });
    

两种方法都有效。我应该选择哪种解决方案,为什么?

谢谢。

因为有疑问为什么这会产生值,这里是完整的代码:

        //Converting events to a "stream" of search results.
        IObservable<SearchResult> resultsFromPageChange = Observable.FromEventPattern<EventArgs>(this,
            "PageChangedEvent")
            .Throttle(TimeSpan.FromMilliseconds(500))
            .Select(async ev =>
            {

                var input = new SearchResultInput()
                {
                    PageSize = PageSize,
                    PageIndex = PageIndex,
                    SearchOptions = _currentSearchOptions,
                    SearchString = SearchString.Value
                };

                return await SearchComponentsPaged(input);

            }).Switch(); //flatten and take most recent.

        SearchString = new ReactiveProperty<string>(""); //Bound to TextBox.Text 

        //Create a "stream" of search results from a string given by user (SearchString)
        SearchResult = SearchString
            .SetValidateNotifyError(s => _componentDataService.ValidateSearchStringLength(s).Errors)
            .Throttle(TimeSpan.FromMilliseconds(500))
            .Select(async term =>
            {
                var input = new SearchResultInput()
                    {
                        PageSize = PageSize,
                        PageIndex = PageIndex,
                        SearchOptions = _currentSearchOptions,
                        SearchString = term
                    };

                return await SearchComponentsPaged(input);

            })
            .Switch()
            .Merge(resultsFromPageChange) //Merge the result of paging and text changing.  
            .ToReactiveProperty();

        //Update Attributes view
        SearchResult.Subscribe(searchResult =>
        {
            if (searchResult != null)
            {
                ActivateAttributesView(searchResult.Components.FirstOrDefault());
                SearchResult.Value.TotalItemsCount = searchResult.TotalItemsCount;
            }

        });

它实际上做的是在搜索字符串更改时向数据库发送搜索请求并获取分页结果,或者在收到 PageChangedEvent 时获取具有相同搜索字符串的另一个页面。 .Merge(...) 是订阅吗?

我会选择你的第二个解决方案。它更灵活,因为不同的订阅者可以选择有不同的副作用。它还分离了关注点,Rx 查询生成数据,订阅者随心所欲地使用数据。

select 的最佳实践以及纯函数(无副作用)的最佳实践。它更清楚地显示了意图。

此外,由于可观察对象是可组合的,并且您可能想在其他地方再次使用数据流,因此最好尽可能明确地说明副作用。