[英]Is there a way to concat non-Redux actions in RxJS / Redux-observable?
After a successful login, I am trying to store a token in local storage before fetching a user's config.成功登录后,我尝试在获取用户配置之前将令牌存储在本地存储中。 At the moment I'm just storing the token from within mergeMap
before fetching the config in the return statement.目前,我只是在获取 return 语句中的配置之前从mergeMap
存储令牌。 However, I'm pretty sure there's a way to use concat
or concatMap
to call the store and fetch functions in sequence.但是,我很确定有一种方法可以使用concat
或concatMap
调用 store 和 fetch 函数。
const authEpic = action$ =>
action$.pipe(
ofType('auth/AUTHENTICATION_SUCCESS'),
mergeMap(action => {
const { jwt } = action.payload;
localStorage.setItem('token', jwt);
return of({
type: 'user/FETCH_CONFIG'
});
})
);
Below is one of my attempts which proved unsuccessful.下面是我的尝试之一,但被证明是不成功的。 Although there might be other ways of handling the storing and fetching in this case from within a component, I would like to know how this pattern should work for other cases I have.尽管在这种情况下可能有其他方法可以从组件内部处理存储和获取,但我想知道这种模式应该如何适用于我拥有的其他情况。
const authEpic = action$ =>
action$.pipe(
ofType('auth/AUTHENTICATION_SUCCESS'),
mergeMap(action => {
const { jwt } = action.payload;
return concat(
localStorage.setItem('token', jwt),
of({ type: 'user/FETCH_CONFIG'})
);
})
);
I would go with the first approach you have stated in your question, as localStorage.setItem()
is synchronous, thus it will always be called, before FETCH_CONFIG
action is returned..我会采用您在问题中陈述的第一种方法,因为localStorage.setItem()
是同步的,因此在返回FETCH_CONFIG
操作之前,它总是会被调用。
However, if you are looking for alternative approaches, I would suggest you to separate the logic by using the tap()
operator before returning the FETCH_CONFIG
action.但是,如果您正在寻找替代方法,我建议您在返回FETCH_CONFIG
操作之前使用tap()
运算符分离逻辑。 This will also ensure that both actions are called in sequence.这也将确保按顺序调用这两个操作。
const authEpic = action$ =>
action$.pipe(
ofType('auth/AUTHENTICATION_SUCCESS'),
tap(({ payload: { jwt } }) => {
localStorage.setItem('token', jwt);
}),
mergeMap((action) => (of({
type: 'user/FETCH_CONFIG'
}))
);
However, if you really want to use concat()
, you will need to wrap the localStorage.setItem()
action in of()
to convert it into an observable, as concat()
requires all members to be observables, and it will need to wait for the first subscription( localStorage.setItem()
) to be completed before the second one( FETCH_CONFIG
) can start.但是,如果您真的想使用concat()
,则需要将localStorage.setItem()
操作包装在of()
以将其转换为可观察对象,因为concat()
要求所有成员都是可观察对象,并且需要在第二个订阅( FETCH_CONFIG
)可以开始之前等待第一个订阅( localStorage.setItem()
)完成。
const authEpic = action$ =>
action$.pipe(
ofType('auth/AUTHENTICATION_SUCCESS'),
mergeMap(action => {
const { jwt } = action.payload;
return concat(
of(localStorage.setItem('token', jwt)),
of({ type: 'user/FETCH_CONFIG'})
);
}),
);
Maybe you can try use last()
operator, Concat will emit when each item in the sequence completes itself so that's why it doesn't work.也许您可以尝试使用last()
运算符,Concat 会在序列中的每个项目自行完成时发出,这就是它不起作用的原因。
reuturn concat(
of(localStorage.setItem('token', jwt)),
of({ type: 'user/FETCH_CONFIG'})
).pipe(last());
concat
is used for executing observables in order as previous complete. concat
用于按照先前完成的顺序执行可观察对象。
Check doc from learnrx.io从learnrx.io检查文档
You can think of concat like a line at an ATM, the next transaction (subscription) cannot start until the previous completes!你可以把 concat 想象成 ATM 上的一条线,下一个交易(订阅)在前一个完成之前不能开始!
In your example, I don't think you need any of those operators since you're not doing anything asynchronous in your flow.在您的示例中,我认为您不需要任何这些运算符,因为您没有在流程中执行任何异步操作。
You could simply change your code with the following:您可以简单地使用以下内容更改您的代码:
action$.pipe(
ofType('auth/AUTHENTICATION_SUCCESS'),
tap(action => localStorage.setItem('token', action.payload)),
mapTo({ type: 'user/FETCH_CONFIG'})
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.