- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
因此,我有一个接收 SUBMIT_LOGIN Action 的史诗,然后它应该触发 generateDeviceId 函数,该函数返回一个以 id 作为有效负载的 Action 。在reducer处理并更新store之后,它应该请求登录,然后将其解析为store,最后将用户重定向到我们的仪表板
const generateDeviceId = (deviceId) => (({type: GENERATE_DEVICE_ID, payload: deviceId}));
const resolveLogin = (response) => ({type: RESOLVE_LOGIN, payload: response});
const submitLogin = (email, password) => ({type: SUBMIT_LOGIN, payload: {email, password}});
const requestLogin = (email, password) => ({type: REQUEST_LOGIN, payload: {email, password}});
const loadAbout = () => ({type: LOAD_ABOUT});
const submitLoginEpic = (action$) =>
action$
.ofType(SUBMIT_LOGIN)
.mapTo(generateDeviceId(uuidv1()))
.flatMap(({payload}) => login(payload.email, payload.password)
.flatMap(({response}) => [resolveLogin(response.content), loadAbout()])
);
login
函数是 ajax
来自 rx-dom
返回一个流:
const AjaxRequest = (method, url, data) => {
const state = store.getState();
const {token, deviceId} = state.user;
return ajax({
method,
timeout: 10000,
body: data,
responseType: 'json',
url: url,
headers: {
token,
'device-id': deviceId,
'Content-Type': 'application/json'
}
});
};
const login = (email, password) => AjaxRequest('post', 'sign_in', {email, password});
uuidv1
函数只是生成一个随 secret 钥(它是一个库)
rx-dom's
ajax 不像 Sergey 的
login$
那样工作可观察的。我们目前正在为此努力。
const generateDeviceId = (deviceId) => (({type: GENERATE_DEVICE_ID, payload: deviceId}));
const resolveLogin = (response) => ({type: RESOLVE_LOGIN, payload: response});
const submitLogin = (email, password) => ({type: SUBMIT_LOGIN, payload: {email, password}});
const requestLogin = (email, password) => ({type: REQUEST_LOGIN, payload: {email, password}});
const loadAbout = () => ({type: LOAD_ABOUT});
const submitLoginEpic = action$ =>
action$.ofType(SUBMIT_LOGIN)
.mergeMap(({payload}) =>
Observable.of(generateDeviceId(uuid()))
.concat(login(payload.email, payload.password)
.concatMap(({response}) => [resolveLogin(response.content), loadAbout()])
two epics
的解决方案。和
.concatMap
运算符以
synchronously
调度 Action 和它
works as expected
.
const generateDeviceId = (deviceId) => (({type: GENERATE_DEVICE_ID, payload: deviceId}));
const resolveLogin = (response) => ({type: RESOLVE_LOGIN, payload: response});
const submitLogin = (email, password) => ({type: SUBMIT_LOGIN, payload: {email, password}});
const requestLogin = (email, password) => ({type: REQUEST_LOGIN, payload: {email, password}});
const loadAbout = () => ({type: LOAD_ABOUT});
const submitLoginEpic = (action$) =>
action$
.ofType(SUBMIT_LOGIN)
.concatMap(({payload}) => [
generateDeviceId(uuid()),
requestLogin(payload.email, payload.password)
]);
const requestLoginEpic = (action$) =>
action$
.ofType(REQUEST_LOGIN)
.mergeMap(({payload}) => login(payload.email, payload.password)
.concatMap(({response}) => [resolveLogin(response.content), loadAbout()])
最佳答案
如果我猜对了,您希望您的史诗产生以下 Action 序列来响应每个 SUBMIT_LOGIN
:
GENERATE_DEVICE_ID -- RESOLVE_LOGIN -- LOAD_ABOUT
GENERATE_DEVICE_ID
需要在
SUBMIT_LOGIN
之后立即发出收到,
RESOLVE_LOGIN
和
LOAD_ABOUT
仅应在
login()
返回的流之后发出发出。
SUBMIT_LOGIN
创建的)
GENERATE_DEVICE_ID
行动和
startWith
运营商正是这样做的:
const submitLoginEpic = action$ =>
action$.ofType(SUBMIT_LOGIN)
.mergeMap(({ payload }) =>
login(payload.email, payload.password)
.mergeMap(({ response }) => Rx.Observable.of(resolveLogin(response.content), loadAbout()))
.startWith(generateDeviceId(uuidv1()))
);
concat
运营商:
obs1.concat(obs2)
订阅
obs2
仅当
obs1
已完成。
login()
需要在
GENERATE_DEVICE_ID
之后调用已发送,您可能希望将其包装在“冷”可观察对象中:
const login$ = payload =>
Rx.Observable.create(observer => {
return login(payload.email, payload.password).subscribe(observer);
});
const submitLoginEpic = action$ =>
action$.ofType(SUBMIT_LOGIN)
.mergeMap(({ payload }) =>
Rx.Observable.of(generateDeviceId(uuidv1()))
.concat(login$(payload).map(({ response }) => resolveLogin(response.content)))
.concat(Rx.Observable.of(loadAbout()))
);
GENERATE_DEVICE_ID
在
login()
之前发出被称为,即序列将是
GENERATE_DEVICE_ID -- login() -- RESOLVE_LOGIN -- LOAD_ABOUT
login()
无法按预期工作是因为它取决于外部状态(
const state = getCurrentState()
),该状态在
login()
时的时间点不同。被调用并且当
login()
返回一个 observable 时已订阅。
AjaxRequest
捕获
login()
时的状态被调用,发生在
GENERATE_DEVICE_ID
之前被派往商店。此时还没有执行网络请求,但是
ajax
observable 已经基于错误的状态进行了配置。
const createInnerObservable = submitLoginAction => {
return Observable.of(generateDeviceId()).concat(login());
}
const submitLoginEpic = action$ =>
action$.ofType(SUBMIT_LOGIN).mergeMap(createInnerObservable);
SUBMIT_LOGIN
行动来了,
mergeMap()
第一次来电
createInnerObservable()
功能。该函数需要创建一个新的 observable 并且它必须调用
generateDeviceId()
和
login()
职能。当
login()
被调用时,状态仍然很旧,因为此时尚未创建内部可观察对象,因此没有机会
GENERATE_DEVICE_ID
被 dispatch 。正因为如此
login()
返回
ajax
observable 配置了旧数据,它成为结果内部 observable 的一部分。尽快
createInnerObservable()
返回,
mergeMap()
订阅返回的内部 observable 并开始发出值。
GENERATE_DEVICE_ID
首先,被分派(dispatch)到商店并改变状态。之后,
ajax
observable(现在是内部 observable 的一部分)被订阅并执行网络请求。但是新状态对此没有影响,因为
ajax
observable 已经用旧数据初始化。
login
进入
Observable.create
推迟调用,直到
Observable.create
返回的 observable已订阅,并且此时状态已经是最新的。
GENERATE_DEVICE_ID
使用react。操作(或其他适合您的域的操作)并发送登录请求,例如:
const submitLogin = payload => ({ type: "SUBMIT_LOGIN", payload });
// SUBMIT_LOGIN_REQUESTED is what used to be called SUBMIT_LOGIN
const submitLoginRequestedEpic = action$ =>
action$.ofType(SUBMIT_LOGIN_REQUESTED)
.mergeMap(({ payload }) => Rx.Observable.of(
generateDeviceId(uuidv1()),
submitLogin(payload))
);
const submitLoginEpic = (action$, store) =>
action$.ofType(SUBMIT_LOGIN)
.mergeMap(({ payload }) => {
// explicitly pass all the data required to login
const { token, deviceId } = store.getState().user;
return login(payload.email, payload.password, token, deviceId)
.map(({ response }) => resolveLogin(response.content))
.concat(loadAbout());
});
redux-observable
基于 RxJS,首先熟悉 Rx 是有意义的。
redux-observable
,绝对值得一看。
关于redux - 发出 Action ,然后使用 redux-observable 和 rxjs 请求并发出另一个 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44706633/
RxJS 中是否有一个运算符可以让我缓冲项目并在信号可观察对象触发时将它们一个一个地放出?有点像bufferWhen,但不是在每个信号上转储整个缓冲区,而是每个信号转储一定数量。它甚至可以转储信号 o
我正在像这样创建我的可观察源(每 5 秒调用一次 api): const obs$ = Observable.interval(5000).switchMap(() => makeApiCall())
我有一个 Action ,然后将触发一个ajax请求。 如果由于某种原因操作失败,我什么也不想做。我没有执行可以执行的无操作功能,而不是创建只返回先前状态的空白操作? export default f
在以下代码中:- RxJS.Observable.of(1,2).first().subscribe((x) => console.log(x);); 给定运营商 first() 是否有必要取消订阅?
我有一种情况,可以在很短的时间内将很多事件发送到流中。我想要一个运算符,它是ojit_code和debounceTime的混合体。 以下演示可用于说明我想拥有的https://stackblitz
我的用例如下:我得到事件,有时会突然发生。如果发生突发,我只需要处理一次即可。去抖动会执行此操作。 但是,去抖动仅给我提供连拍的最后一个元素,但我需要了解连拍中的所有元素才能汇总(使用平面图)。 这可
简化以下代码示例的方法是什么? 我找不到合适的运算符..有人可以举一个简短的例子吗? this.returnsObservable1(...) .subscribe( success =>
在RxJS 6中,如何导入静态合并功能以合并Observable列表? 我希望能够做到: const merged$ = merge( obs1$, obs2$, obs3$
我正在阅读 RxJS 的官方文档,然后我意识到它们都在做完全相同的事情。 对我来说,它们看起来完全相似。 如果有区别请指出。 最佳答案 我将根据它们的 Time 版本来描述它们之间的区别,因为这是我最
我对基本的 RxJS 概念有点熟悉,比如 Observables、Observers 和 Subjects,但是 RxJS Notifications概念对我来说是全新的。 它有什么用?我应该什么时候
从 rxjs 6.5 切换到 rxjs 7 后,我遇到了这个奇怪的错误。我不确定这是 rxjs 7 的类型问题还是 stackblitz ( https://stackblitz.com/edit/r
以前我只能使用此代码导入使用过的运算符: import 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/oper
combineLatest 函数可以从 rxjs 和 rxjs/operators 导入。 当我从 rxjs/operators 导入它时(就像我导入 combineAll 我收到以下错误: TS23
我有一系列事件通过 fromEventPattern 进行像这样: fromEventPattern(addEventHandler).subscribe(ps$); 由于业务怪癖,我预计有时会抛出异
我是 rxjs 的新手,无法解决这个问题: 我有两个流: 一个有传入的对象 ---a----b----c----d-----> 一个是从列表中选择的对象 ----------------c---->
如果一个 observable 完成,我是否仍然需要取消订阅/处置(在 RxJS 中)该 observable 以删除 Observer(防止内存泄漏),或者一旦 onComplete 或 onErr
我有这样的订阅: this.test.subscribe(params => { ...some code }); 如果我传递回调函数而不是箭头函数,则缺少上下文。 我想将上下文绑定(bind)到
我有一个可观察的: messages: string[] = ['a', 'b', 'c']; const source = from(messages) 你如何延迟它,所以当有人订阅它时,它
我可以让 observable 触发一次该值。但我希望它在变量的值发生变化时发生。实际上我需要一个观察者。这就是我认为 observable 的意义所在。观察事物的值(value)或状态并更新订阅它的
我有以下代码: const fetchBook = (bookId: number) => { const title = 'Book' + bookId; console.log('
我是一名优秀的程序员,十分优秀!