简体   繁体   English

startWith运算符Rxjs无法按预期工作

[英]startWith operator Rxjs not working as expected

I'm new to Observables and reactive programming rxjs, I have added the library redux-observable to my react/redux application to start playing with it. 我是Observables和反应式编程rxjs的新手,我已经在我的react / redux应用程序中添加了redux-observable库以开始使用它。

I have created an epic for the login process, basically what I want is, once the LOGIN_REQUEST action has been fired, first of all I launch the SET_LOADING action, to display a spinning wheel to the user while the operation is not done, and then I make a rest request to the server to fetch the user. 我为登录过程创建了一个史诗,基本上我想要的是,一旦触发了LOGIN_REQUEST操作,我首先启动SET_LOADING操作,以在操作未完成时向用户显示一个旋转的转轮,然后我向服务器发出休息请求以获取用户。

This is the code I wrote: 这是我写的代码:

  const loginEpic = (action$) => {
  console.log('EPIC LOGIN EXECUTED');
  return action$.filter(action => action.type === LOGIN_REQUEST)
        .mergeMap(action => ajax.post(getUrl(constants.LOGIN),
            action.payload))
        .map(response => setUser(response.response))
        .takeUntil(action$.ofType(LOGIN_REQUEST_CANCELLED));
        .startWith(setLoading(true));
};

I'm using the operator startWith to launch the SET_LOADING action as soon the LOGIN_REQUEST is fired (this is the behaviour I would expect). 触发LOGIN_REQUEST后,我正在使用运算符startWith启动SET_LOADING操作(这是我期望的行为)。 However, I don't know why the SET_LOADING action is being fired when the application is first loaded, without even a previous LOGIN_REQUEST action. 但是,我不知道为什么在首次加载应用程序时甚至没有先前的LOGIN_REQUEST操作时都会触发SET_LOADING操作。

I know the problem is related to the startWith operator because if I remove , then the SET_LOADING action is not fired. 我知道问题与startWith运算符有关,因为如果我删除,则不会触发SET_LOADING操作。 So, what am I doing wrong? 那么,我在做什么错呢? Why this SET_LOADING action is being fired always, and not only after a LOGIN_REQUEST action? 为什么总是(不仅在执行LOGIN_REQUEST之后)触发此SET_LOADING操作?

Thanks 谢谢

Epic is just an observable and whenever it produces an action it will be dispatched. 史诗只是一个可观察到的东西,只要它产生一个动作,它就会被调度。 If you use startWith like this then you're saying that whoever will start subscription will immediately receive setLoadingAction. 如果您像这样使用startWith,那么您说的是将开始进行订阅的任何人都将立即收到setLoadingAction。 Instead you should raise loadingAction only if your filter is true. 相反,只有在您的过滤器为true时,才应提高loadingAction。

Something along these lines: 遵循以下原则:

 const loginEpic = (action$) => {
  console.log('EPIC LOGIN EXECUTED');
  return action$.filter(action => action.type === LOGIN_REQUEST)
        .mergeMap(action => Observable.merge(
              Observable.of(setLoading(true)), 
              Observable.fromPromise(ajax.post(getUrl(constants.LOGIN),
                   action.payload))
        .map(response => setUser(response.response))
        .takeUntil(action$.ofType(LOGIN_REQUEST_CANCELLED)));
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM