相当于 rxjs 中可观察到的 redux 'getState'

Posted

技术标签:

【中文标题】相当于 rxjs 中可观察到的 redux \'getState\'【英文标题】:equivalent of redux 'getState' in from an observable in rxjs相当于 rxjs 中可观察到的 redux 'getState' 【发布时间】:2018-08-29 04:16:13 【问题描述】:

我正在玩 rxjs,目的是掌握 JS 中的反应式和函数式编程。

我有以下琐碎的应用程序:

import Rx from 'rxjs'

const domContainer = document.querySelector('[data-container]')

const clickElement = document.querySelector('[data-init-fetch]')
const loader = document.querySelector('.loader')

// only emit when all the data is returned
const fetchData = (first, last) => Rx.Observable.range(first, last)
  .flatMap(async n => 
    const res = await fetch(`https://swapi.co/api/people/$n`)
    return await res.json()
  )
  .reduce((acc, item) => [...acc, item], [])

const createEventStream = (
  domNode,
  createRequestDataAction,
  createReceiveDataAction,
) => 

  const handleButtonClick = Rx.Observable.fromEvent(domNode, 'click')

  const request = fetchData(1, 10)
  // i'd like to be be able to 'getState' in here to use correct offset and 
  // fetch the next ten entries

  const setIsFetching = handleButtonClick
    .map(createRequestDataAction)

  // fetch data on request
  const requestData = handleButtonClick
    .switchMapTo(request)
    .map(createReceiveDataAction)

  return Rx.Observable.merge(
    requestData,
    setIsFetching,
  )


const initState = 
  offset: 1,
  isFetching: false,
  chars: ,


const eventStream = createEventStream(
  domNode: clickElement,
  createReceiveDataAction,
  createRequestDataAction,
)
  .scan(reducer, initState)
  .subscribe(
    renderMarkup,
  )

function reducer (
  state = initState,
  
    type,
    payload,
  
) 
  // do some reducery stuff in here and return new state


function renderMarkup(state) 
  // renders the state to the DOM


function createReceiveDataAction(data) 
  return 
    type: 'apiReceive',
    payload: 
      chars: data,
    ,
  


function createRequestDataAction() 
  return  type: 'apiRequest' 
  // this action will update offset += 10 in the reducer

我的问题是,如果我在调度 fetchData 操作时使用 redux(虽然我不在这里),我只需调用 getState() 从当前状态获取 offset 并在 @987654323 中使用它@动作。

有没有办法在上面的代码中使用 rxjs(并且没有 redux)来做到这一点?例如,我想在fetchData 调用中使用状态变量。

我是否需要创建另一个 Observable 来处理offset?还是我以完全错误的方式处理这个问题?

为清晰起见进行了编辑。

【问题讨论】:

【参考方案1】:

我不太清楚你想要达到什么目的。

我有几个可以帮助你的 cmets。

使用 Observable 代替 Promise

您可以转换此代码

const fetchData = (first, last) => Rx.Observable.range(first, last)
  .flatMap(async n => 
    const res = await fetch(`https://swapi.co/api/people/$n`)
    return await res.json()
  )
  .reduce((acc, item) => [...acc, item], [])

到这里

const fetchData = (first, last) => Rx.Observable.range(first, last)
  .mergeMap(n =>    // mergeMap is the new name of flatMap
    const promiseCall = fetch(`https://swapi.co/api/people/$n`)
    return Observable.fromPromise(promiseCall).map(res => res.json())
  )
  .reduce((acc, item) => [...acc, item], [])

您也可以查看this question 以找到其他方法来执行许多 http 请求并仅在所有请求都完成后返回。

在 eventStream 中存储订阅

如果您运行以下代码,您最终会将订阅存储在变量 eventStream 中。然后可以使用 Subcription 实例取消订阅。

const eventStream = createEventStream(
  domNode: clickElement,
  createReceiveDataAction,
  createRequestDataAction,
)
  .scan(reducer, initState)
  .subscribe(
    renderMarkup,
  )

在 fetchData 调用中使用状态信息

我假设您将状态信息存储在 state 变量引用的对象中。

如果这是正确的,我会按照这些思路进行操作

const createEventStream = (
  domNode,
  createRequestDataAction,
  createReceiveDataAction,
) => 

  Rx.Observable.fromEvent(domNode, 'click')
    .map(createRequestDataAction)
    .concat(fetchData(initState.offset, initState.offset + 10))
    .map(createReceiveDataAction)


您甚至可以考虑使用类似这样的方式删除 reduce 函数。

const createEventStream = (
  domNode
) => 

  Rx.Observable.fromEvent(domNode, 'click')
    .do(_ => state.fetching = true)
    .concat(fetchData(initState.offset, initState.offset + 10))
    .do(_ => initState.offset = initState.offset + 10)
    .do(_ => initState.fetching = false)


我无法测试我的建议,所以我不确定是否有错误。

【讨论】:

谢谢。关于我想要实现的目标,我会尝试访问状态以在 fetchData 调用中使用。这样我就可以调用fetchData(offset, offset + 10) 并从 api 中检索接下来的 10 个条目。在 redux 操作中,我得到 dispatchgetState,我可以调用它们来检索当前状态(或偏移量)。但是,我在这里没有使用 redux。我想访问作为 eventStream 的一部分传递给 reducer 的状态。这有意义吗? 我认为这是我们在这种情况下能做的最好的事情。我上面的代码只是为了掌握 rxJs。我知道在现实生活中这可能不会以这种方式完成。感谢您的意见。

以上是关于相当于 rxjs 中可观察到的 redux 'getState'的主要内容,如果未能解决你的问题,请参考以下文章

RxJS - 发生错误时观察到的不会完成

退订 RxJS 可观察到的影响

使用RXJS实现React中的redux功能

在 ViewController 中可观察到的单元测试 RxSwift

Angular2 beta.12 和 RxJs 5 beta.3 的可观察到的错误

使用表数据中可观察到的剔除值来应用 CSS 类