如何仅在另一部史诗结束时才发出史诗?
How to emit an epic only if another epic finished?
我有 2 个实体:收款人和交易。我有 payeeCreateEpic
过滤 started
发出 finished
/failed
的常规链。 transactionCreateEpic
.
也一样
为了简单起见,假设收款人只有 UUID 和姓名。然而,交易可以有 3 种可能性之一:未附加到任何收款人(有效负载有 payee: null
),附加到现有收款人(在 UI 上,用户有一个所有收款人的下拉列表,他可以在其中选择一个,具有 payee: payee-uuid
) 或附加到 非 现有收款人的有效载荷(在 UI 上,用户可以选择创建不保存到后端的收款人,但是如果保存了整个交易,则应该保存,在我发送的有效负载中 payee: payee-name
).
现在,如果提交创建交易时没有收款人或现有收款人,我只需转到 POST /transactions
并等待它解决以发出 finished
或 failed
操作transactionCreateEpic
.
但是,如果 !isUuid(txPayload.payee)
的计算结果为真,在 transactionCreateEpic
的史诗中,我想用收款人姓名启动 payeeCreateEpic
,并等待 finished
=>然后从后端使用 payee-id 创建交易,或者 failed
=> 中止交易(并向用户显示错误)。
我不确定该怎么做,因为在事务史诗中,我已经在 TRANSACTION_CREATE_STARTED
操作的过滤器中,但不确定如何订阅 [=11] 发出的另一个操作=].
一些代码:
const createPayeeEpic = (actions$: Observable<Action>) =>
actions$.pipe(
filter(CreateAction.start.match),
mergeMap((action) =>
from(MoneyPinApiClient.getInstance().payee.create(CreateRequestAdapter(action.payload))).pipe(
map((response) => CreateAction.success({
params: action.payload,
result: CreateResultAdapter(response.data)
})),
catchError((err) => of(
<any>CreateAction.failure({params: action.payload, error: err}),
<any>MoneyPinApiErrorAction(err)
))
)
)
);
const createTransactionEpic = (actions$: Observable<Action>) =>
actions$.pipe(
filter(CreateAction.start.match),
mergeMap((action) => {
if(!isUuid(action.payload.payee) {
**EMIT PayeeCreateAction.start({name: action.payload.payee})**
**WAIT FOR PayeeCreateAction.success (or PayeeCreateAction.failure)**
action.payload.payee = resultOf(PayeeCreateAction.success).id;
}
return from(MoneyPinApiClient.getInstance().transaction.create(CreateRequestAdapter(action.payload))).pipe(
map((response) => CreateAction.success({
params: action.payload,
result: CreateResultAdapter(response.data)
})),
catchError((err) => of(
<any>CreateAction.failure({params: action.payload, error: err}),
<any>MoneyPinApiErrorAction(err)
))
)
})
);
看看 createTransactionEpic
,这是我在实际启动 createPayeeEpic + 等待成功或失败时遇到困难的地方。
您的问题看起来像是线程同步问题。
使用一种线程同步模式。
例如。 https://en.wikipedia.org/wiki/Monitor_(synchronization)
解决方案是将事务的实际创建提取到某个工厂方法:
const transactionCreateStreamFactory = (action: MoneyPinAction<CreateActionParams>) =>
from(MoneyPinApiClient.getInstance().transaction.create(CreateRequestAdapter(action.payload))).pipe(
concatMap((response) => CreateAction.success({
params: action.payload,
result: CreateResultAdapter(response.data)
})),
catchError((err) => of(
<any>CreateAction.failure({params: action.payload, error: err}),
<any>MoneyPinApiErrorAction(err)
))
);
然后创建交易史诗实际上是这样的:
const createTransactionEpic = (actions$: Observable<Action>) =>
actions$.pipe(
filter(CreateAction.start.match),
mergeMap((action) => {
const {payee, payload} = action.payload;
if (payee && payload.payee_id) {
return merge(
actions$.pipe(
filter(PayeeCreateAction.success.match),
filter((payeeResponse) => payeeResponse.payload.result.payee.id === payload.payee_id),
take(1),
mergeMap(() => transactionCreateStreamFactory(action)),
),
actions$.pipe(
filter(PayeeCreateAction.failure.match),
filter((payeeResponse) => payeeResponse.payload.params.payload.id === payload.payee_id),
take(1),
map(() => CreateAction.failure({
params: action.payload,
error: new Error("failed to create payee")
}))
)
).pipe(
startWith(PayeeCreateAction.start({
notebook_id: action.payload.notebook_id,
payload: {id: payload.payee_id, name: payee}
}))
);
} else {
return transactionCreateStreamFactory(action);
}
})
);
因此,如果在创建过程中给出了带有 id 的收款人,我将启动另一个管道,该管道监听 payee.success
或 payee.failure
操作,过滤相关操作(以防多个操作这种类型可能会在并发创建或其他过程中出现),只侦听一次(take(1)
),然后将其合并映射到实际的创建事务史诗,整个流从 payee.start
处理的操作开始收款人史诗(它会发出收款人操作的成功/失败)。
我有 2 个实体:收款人和交易。我有 payeeCreateEpic
过滤 started
发出 finished
/failed
的常规链。 transactionCreateEpic
.
为了简单起见,假设收款人只有 UUID 和姓名。然而,交易可以有 3 种可能性之一:未附加到任何收款人(有效负载有 payee: null
),附加到现有收款人(在 UI 上,用户有一个所有收款人的下拉列表,他可以在其中选择一个,具有 payee: payee-uuid
) 或附加到 非 现有收款人的有效载荷(在 UI 上,用户可以选择创建不保存到后端的收款人,但是如果保存了整个交易,则应该保存,在我发送的有效负载中 payee: payee-name
).
现在,如果提交创建交易时没有收款人或现有收款人,我只需转到 POST /transactions
并等待它解决以发出 finished
或 failed
操作transactionCreateEpic
.
但是,如果 !isUuid(txPayload.payee)
的计算结果为真,在 transactionCreateEpic
的史诗中,我想用收款人姓名启动 payeeCreateEpic
,并等待 finished
=>然后从后端使用 payee-id 创建交易,或者 failed
=> 中止交易(并向用户显示错误)。
我不确定该怎么做,因为在事务史诗中,我已经在 TRANSACTION_CREATE_STARTED
操作的过滤器中,但不确定如何订阅 [=11] 发出的另一个操作=].
一些代码:
const createPayeeEpic = (actions$: Observable<Action>) =>
actions$.pipe(
filter(CreateAction.start.match),
mergeMap((action) =>
from(MoneyPinApiClient.getInstance().payee.create(CreateRequestAdapter(action.payload))).pipe(
map((response) => CreateAction.success({
params: action.payload,
result: CreateResultAdapter(response.data)
})),
catchError((err) => of(
<any>CreateAction.failure({params: action.payload, error: err}),
<any>MoneyPinApiErrorAction(err)
))
)
)
);
const createTransactionEpic = (actions$: Observable<Action>) =>
actions$.pipe(
filter(CreateAction.start.match),
mergeMap((action) => {
if(!isUuid(action.payload.payee) {
**EMIT PayeeCreateAction.start({name: action.payload.payee})**
**WAIT FOR PayeeCreateAction.success (or PayeeCreateAction.failure)**
action.payload.payee = resultOf(PayeeCreateAction.success).id;
}
return from(MoneyPinApiClient.getInstance().transaction.create(CreateRequestAdapter(action.payload))).pipe(
map((response) => CreateAction.success({
params: action.payload,
result: CreateResultAdapter(response.data)
})),
catchError((err) => of(
<any>CreateAction.failure({params: action.payload, error: err}),
<any>MoneyPinApiErrorAction(err)
))
)
})
);
看看 createTransactionEpic
,这是我在实际启动 createPayeeEpic + 等待成功或失败时遇到困难的地方。
您的问题看起来像是线程同步问题。 使用一种线程同步模式。 例如。 https://en.wikipedia.org/wiki/Monitor_(synchronization)
解决方案是将事务的实际创建提取到某个工厂方法:
const transactionCreateStreamFactory = (action: MoneyPinAction<CreateActionParams>) =>
from(MoneyPinApiClient.getInstance().transaction.create(CreateRequestAdapter(action.payload))).pipe(
concatMap((response) => CreateAction.success({
params: action.payload,
result: CreateResultAdapter(response.data)
})),
catchError((err) => of(
<any>CreateAction.failure({params: action.payload, error: err}),
<any>MoneyPinApiErrorAction(err)
))
);
然后创建交易史诗实际上是这样的:
const createTransactionEpic = (actions$: Observable<Action>) =>
actions$.pipe(
filter(CreateAction.start.match),
mergeMap((action) => {
const {payee, payload} = action.payload;
if (payee && payload.payee_id) {
return merge(
actions$.pipe(
filter(PayeeCreateAction.success.match),
filter((payeeResponse) => payeeResponse.payload.result.payee.id === payload.payee_id),
take(1),
mergeMap(() => transactionCreateStreamFactory(action)),
),
actions$.pipe(
filter(PayeeCreateAction.failure.match),
filter((payeeResponse) => payeeResponse.payload.params.payload.id === payload.payee_id),
take(1),
map(() => CreateAction.failure({
params: action.payload,
error: new Error("failed to create payee")
}))
)
).pipe(
startWith(PayeeCreateAction.start({
notebook_id: action.payload.notebook_id,
payload: {id: payload.payee_id, name: payee}
}))
);
} else {
return transactionCreateStreamFactory(action);
}
})
);
因此,如果在创建过程中给出了带有 id 的收款人,我将启动另一个管道,该管道监听 payee.success
或 payee.failure
操作,过滤相关操作(以防多个操作这种类型可能会在并发创建或其他过程中出现),只侦听一次(take(1)
),然后将其合并映射到实际的创建事务史诗,整个流从 payee.start
处理的操作开始收款人史诗(它会发出收款人操作的成功/失败)。