使用 FetchJsonP / Redux / React 调用 API 时的错误处理
Error Handling on API Call with FetchJsonP / Redux / React
嘿,我正在尝试找出一种方法来处理错误并 api 在 redux 史诗中调用,我已经查看了这个文档:
https://redux-observable.js.org/docs/recipes/ErrorHandling.html
我没有任何错误,但没有任何反应,代码似乎在循环
/**
* Request the JSON guide to the API
* and then dispatch requestGuideFulfilled & requestGameTask actions
*
* @param action$
*/
export function requestGuide(action$) {
return action$.ofType(REQUEST_GUIDE)
.mergeMap(({id}) => fetchJsonp(`${API_URL}/guide/${id}/jsonp`)
.catch(error => requestGuideFailed(error))
)
.mergeMap(response => response.json())
.mergeMap(json => requestGuideFulfilled(json))
.map(json => requestGameTask(json))
}
export function manageRequestGuideError(action$) {
return action$.ofType(REQUEST_GUIDE_FAILED)
.subscribe(({error}) => {
console.log('Error',error)
})
}
有什么想法吗?谢谢!
[更新]:即使在获取时我也有错误:
You provided an invalid object where a stream was expected. You can
provide an Observable, Promise, Array, or Iterable.
有很多问题,所以我会尽力详细说明。坦率地说,RxJS不容易。我鼓励您在使用 redux-observable 之前花一些时间学习基础知识,除非您当然只是在空闲时间进行实验以获得乐趣并且喜欢痛苦。
不要引入 redux-observable 之类的东西也很重要,除非你 真的 需要复杂的副作用管理。有点不幸的是,文档目前只有简单的示例,但 redux-observable 的真正目的是使复杂的东西,如多路复用 websockets,详尽的 time-based 排序等,以需要真正了解 RxJS 为代价变得更容易。所以我想我的意思是,如果你确实需要 redux,请确保你也需要 redux-observable 或者可以不用 redux-thunk。 redux-observable 的制造商之一说服人们不要使用它可能看起来很有趣,但我只是看到疯狂的人使用 redux-observable/redux-saga 之类的东西来做一些根本不能证明其复杂性的事情他们带来。 你虽然最了解你的需求,所以不要以此为教条或无理气馁<3
None 此答案中的代码已经过测试,因此可能需要稍作更正。
You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
此错误可能是由 .mergeMap(json => requestGuideFulfilled(json))
引起的。看起来 requestGuideFulfilled
是一个 action creator,但这里没有包含来源,所以我不能确定。 mergeMap
又名 flatMap
希望你 return 另一个流(通常是一个 Observable),所以一个动作 POJO 需要包装在一个 Observable 中,就像 Observable.of(requestGuideFulfilled(json))
但在这种情况下使用 mergeMap
是不必要的。它可能只是一个普通的 map()
.
export function manageRequestGuideError(action$) {
return action$.ofType(REQUEST_GUIDE_FAILED)
.subscribe(({error}) => {
console.log('Error',error)
})
}
在redux-observable中所有Epics必须return一个Observable。此 Epic 是 return 订阅可观察对象(subscribe()
的 return 值)。这实际上确实会产生错误,但是由于 bug in RxJS it's been silently swallowed.
相反,您可以使用 do
和 ignoreElements
创建一个 Observable 来监听该操作,将 属性 记录下来,然后忽略它(永远不会自己发出任何东西)。所以基本上是"read only"。
export function manageRequestGuideError(action$) {
return action$.ofType(REQUEST_GUIDE_FAILED)
.do(({error}) => {
console.log('Error',error)
})
.ignoreElements();
}
下一个也是最大的问题是您放置 catch
的位置。重要的是要了解使用 RxJS 意味着我们如何将 Observable 链接在一起——"operators" 基本上采用一个源和 return 另一个 Observable,后者将延迟对通过它们传输的数据应用一些操作。这与使用数组(例如 arr.map().filter()
)的函数式编程非常相似,但有两个主要区别:Observables 是惰性的并且它们有 time-dimension.
运算符的工作原理
所以考虑这个 Observable 链:
Observable.of(1, 2, 3)
.map(num => num.toString())
.filter(str => str !== '2');
.subscribe(value => console.log(value));
- 我们创建一个 Observable,当订阅时,它会同步发出 1、2、3。
- 我们将
map
运算符应用于该源,它创建了一个新的 Observable,当订阅时,它本身将订阅我们应用它的源:我们的 Observable 1、2、3。
- 然后我们应用
filter
运算符to the Observable returned by
map. As you might have guessed,
filterreturns a new Observable that, when subscribed to, will itself subscribe to the source we applied it to: our Observable of strings we mapped. Because that
map` Observable 本身被应用到一个源,然后它也会订阅它的源, 拉入第一个数字并开始地图 -> 过滤操作。
将这些中间 Observable 存储为变量可能会有所帮助,以揭开神秘面纱。
const source1: Observable<number> = Observable.of(1, 2, 3);
const source2: Observable<string> = source1.map(num => num.toString());
const result: Observable<string> = source2.filter(str => str !== '2');
内部 Observables
当我们使用像 mergeMap
、switchMap
、concatMap
这样的运算符时,我们是说我们想将每个值映射到另一个 "inner" Observable 的值将是在前一个内部 Observable 之后合并、切换或排队(concat)。它们有不同的重要区别,但如果您不熟悉它们,可以参考很多资源。
在您的例子中,我们使用的是 mergeMap
,它还有一个别名 flatMap
,这是函数式编程中更广为人知的术语。 mergeMap
将为您的投影函数提供每个值,并同时为您 return 订阅 Observable。每个内部 Observable 的值都合并在一起。
在函数式编程中,他们更常称此为扁平化,而不是合并。因此,首先在 Arrays
的上下文中考虑这个 merging/flattening 可能会再次有所帮助
Array.prototype.map
[1, 3, 5].map(value => {
return [value, value + 1];
});
// [[1, 2], [3, 4], [5, 6]] Array<Array<number>>
这导致了一个由数字组成的数组 Array<Array<number>>
,但是如果我们想要一个单一的扁平化数组呢?输入 flatMap
.
Array.prototype.flatMap (stage 2 TC39 proposal)
[1, 3, 5].flatMap(value => {
return [value, value + 1];
});
// [1, 2, 3, 4, 5, 6] Array<number>
JavaScript 数组还正式有 flatMap
,但在撰写本文时它是 stage 2 TC39 proposal。它遵循与典型 flatMap
相同的语义:对于数组中的每个项目,将其映射到投影函数提供的另一个数组,然后将每个项目展平为一个新数组。
对于 Observables,它几乎是一样的,除了它们是惰性的并且有一个时间维度:
Observable.of(1, 3, 5).map(value => {
return Observable.of(value, value + 1);
});
// Observable.of(1, 2)..Observable.of(3, 4)..Observable.of(5, 6) | Observable<Observable<number>>
我们将每个数字映射到它们自己的两个数字的 Observable 中。所以 higher-order Observable Observable<Observable<number>>
可能不是我们想要的在大多数情况下。
Observable.of(1, 3, 5).flatMap(value => {
return Observable.of(value, value + 1);
});
// 1..2..3..4..5..6 | Observable<number>
现在我们只有所有数字的流。完美!
错误处理
结合我们对操作链接和 Observable 扁平化的理解,我们来谈谈错误处理。希望这本入门书能让下一部分更容易理解。
如果我们链式 Observables 中的任何一个抛出错误,它将以与值相同的方式在链中传播,但基本上是在它自己的 "channel" 中。所以如果我们有一个 Observable 链 a -> b -> c
并且在 a
中发生错误,它将被发送到 b
然后 c
。当每个 Observable 收到错误时,它可以以某种方式处理它,或者选择将它传递给任何订阅它的人。当它这样做时,该订阅将终止并且不再侦听来自其源的未来消息。
大多数运算符只是传递错误(同时终止),所以如果您没有使用像 catch
这样的特殊错误处理运算符,错误就会传播直到它到达您的观察者——您自己传递给的那个.subscribe(next, error, complete)
。如果您提供了该错误处理程序,它将被调用,如果没有,它将作为正常的 JavaScript 异常重新抛出。
为了最终得到你的代码,让我们从头开始;我认为你真正想要的是:
function getGuide(id) {
const promise = fetchJsonp(`${API_URL}/guide/${id}/jsonp`)
.then(res => res.json());
return Observable.from(promise);
}
export function requestGuide(action$) {
return action$.ofType(REQUEST_GUIDE)
.mergeMap(({id}) =>
getGuide(id)
.mergeMap(json => Observable.of(
requestGuideFulfilled(json),
requestGameTask(json)
))
.catch(error => Observable.of(
requestGuideFailed(error)
))
)
}
现在我们来分解一下。
Promise 与 Observable
您首先会看到我将您的 fetchJsonp
提取到 getGuide
函数中。您也可以将这段代码放在史诗中,但是如果您决定测试,将它分开将使您更容易模拟它。
我尽快将 Promise 包装在 Observable 中。主要是因为如果我们选择使用 RxJS,我们应该选择 all-in,尤其是为了防止以后出现混淆。例如Promise 和 Observable 实例都有 catch
方法,因此如果您开始混合使用两者,很容易导致错误。
理想情况下我们会完全使用 Observables 而不是 Promises,因为 Promises 不能被取消(所以你不能取消实际的 AJAX 请求 + JSON 解析本身),尽管如果你把它包装在一个 Observable 并在 promise 解析之前取消订阅,Observable 将正确地忽略 promise 稍后解析或拒绝的内容。
发出多个动作?
它不是 100% 清楚,但看起来你打算发出两个动作以响应成功取回 JSON。您之前的代码实际上将 JSON 映射到 requestGuideFulfilled()
操作,但是下一个运算符将该操作映射到 requestGameTask()
(它不接收 JSON,它接收requestGuideFulfilled()
行动)。记得上面,关于运算符如何成为 Observables 链,值流经它们。
要解决这个问题,我们需要思考"in streams"。我们的 getGuide()
Observable 将发出一个值,即 JSON。给定单个 (1) 值,我们希望将其映射到多个其他值,在本例中为两个操作。所以我们要改造one-to-many。我们需要使用 mergeMap
、switchMap
或 concatMap
之一。在这种情况下,由于我们的 getGuide()
永远不会发出超过一项,所以所有这三个运算符都会有相同的结果,但了解它们很重要,因为它通常 很重要 所以记住这一点!在这种情况下,我们只使用 mergeMap
。
.mergeMap(json => Observable.of(
requestGuideFulfilled(json),
requestGameTask(json)
))
Observable.of
支持任意数量的参数,并将按顺序发出每个参数。
捕获错误
因为我们的 Observable 链是......嗯..链 hehe 值在它们之间通过管道传输。正如我们在上面了解到的那样,由于这个 where 你在这些链中放置错误处理很重要。这其实和传统的异常处理,甚至是 promises 的错误处理没有太大区别,但是 Promises 没有 "operators",所以人们通常不会 运行 陷入这种困惑。
catch
运算符是最常见的,它与 catch
Promise 非常相似,除了 你必须 return 一个你想要的值的 Observable ,而不是值本身。 Observable.of
在这里很常见,因为大多数情况下我们只想按顺序发出一个或多个项目。
.catch(error => Observable.of(
requestGuideFailed(error)
))
每当我们应用此运算符的源发出错误时,它都会捕获它并发出 requestGuideFailed(error)
然后 complete()
.
因为它发出错误操作,我们应用于此 .catch()
** 的结果的任何运算符也可以对我们的 catch
发出的值进行操作。
getJsonSomehow()
.catch(error => Observable.of(
someErrorAction(error)
))
.map(json => {
// might be the JSON, but also might be the
// someErrorAction() action!
return someSuccessAction();
})
虽然不是 redux-observable 独有的(因为 redux-observable 主要只是一个小型库和一个约定,使用 RxJS)你会经常看到 Epics 遵循类似的模式。
- 侦听特定操作
- 然后将该动作合并或切换到执行副作用的内部 Observable 中
- 当副作用成功时,我们
map
将其作为成功操作
- 以防出错,我们在
mergeMap
/switchMap
中放置一个 catch
,但最常见的是在内链的末尾,o 我们发出的任何动作都不会意外改变。
您有望从 redux-observable 文档中识别出一般模式:
function exampleEpic(action$) {
return action$.ofType(EXAMPLE)
.mergeMap(action =>
getExample(action.id)
.map(resp => exampleSuccess(resp))
.catch(resp => Observable.of(
exampleFailure(resp)
))
);
}
将这些知识应用到我们之前的工作中:
getGuide(id)
.mergeMap(json => Observable.of(
requestGuideFulfilled(json),
requestGameTask(json)
))
.catch(error => Observable.of(
requestGuideFailed(error)
))
我想就是这样。
呸!抱歉,那是 long-winded。你完全有可能知道其中的一些或全部,所以如果我在宣讲合唱团,请原谅我!我开始写一些简短的东西,但在澄清之后不断添加澄清。哈哈
如果您正在苦苦挣扎,请务必确保使用 RxJS 和 redux-observable(或任何复杂的中间件)是您的应用程序所必需的复杂性。
嘿,我正在尝试找出一种方法来处理错误并 api 在 redux 史诗中调用,我已经查看了这个文档: https://redux-observable.js.org/docs/recipes/ErrorHandling.html 我没有任何错误,但没有任何反应,代码似乎在循环
/**
* Request the JSON guide to the API
* and then dispatch requestGuideFulfilled & requestGameTask actions
*
* @param action$
*/
export function requestGuide(action$) {
return action$.ofType(REQUEST_GUIDE)
.mergeMap(({id}) => fetchJsonp(`${API_URL}/guide/${id}/jsonp`)
.catch(error => requestGuideFailed(error))
)
.mergeMap(response => response.json())
.mergeMap(json => requestGuideFulfilled(json))
.map(json => requestGameTask(json))
}
export function manageRequestGuideError(action$) {
return action$.ofType(REQUEST_GUIDE_FAILED)
.subscribe(({error}) => {
console.log('Error',error)
})
}
有什么想法吗?谢谢!
[更新]:即使在获取时我也有错误:
You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
有很多问题,所以我会尽力详细说明。坦率地说,RxJS不容易。我鼓励您在使用 redux-observable 之前花一些时间学习基础知识,除非您当然只是在空闲时间进行实验以获得乐趣并且喜欢痛苦。
不要引入 redux-observable 之类的东西也很重要,除非你 真的 需要复杂的副作用管理。有点不幸的是,文档目前只有简单的示例,但 redux-observable 的真正目的是使复杂的东西,如多路复用 websockets,详尽的 time-based 排序等,以需要真正了解 RxJS 为代价变得更容易。所以我想我的意思是,如果你确实需要 redux,请确保你也需要 redux-observable 或者可以不用 redux-thunk。 redux-observable 的制造商之一说服人们不要使用它可能看起来很有趣,但我只是看到疯狂的人使用 redux-observable/redux-saga 之类的东西来做一些根本不能证明其复杂性的事情他们带来。 你虽然最了解你的需求,所以不要以此为教条或无理气馁<3
None 此答案中的代码已经过测试,因此可能需要稍作更正。
You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
此错误可能是由 .mergeMap(json => requestGuideFulfilled(json))
引起的。看起来 requestGuideFulfilled
是一个 action creator,但这里没有包含来源,所以我不能确定。 mergeMap
又名 flatMap
希望你 return 另一个流(通常是一个 Observable),所以一个动作 POJO 需要包装在一个 Observable 中,就像 Observable.of(requestGuideFulfilled(json))
但在这种情况下使用 mergeMap
是不必要的。它可能只是一个普通的 map()
.
export function manageRequestGuideError(action$) {
return action$.ofType(REQUEST_GUIDE_FAILED)
.subscribe(({error}) => {
console.log('Error',error)
})
}
在redux-observable中所有Epics必须return一个Observable。此 Epic 是 return 订阅可观察对象(subscribe()
的 return 值)。这实际上确实会产生错误,但是由于 bug in RxJS it's been silently swallowed.
相反,您可以使用 do
和 ignoreElements
创建一个 Observable 来监听该操作,将 属性 记录下来,然后忽略它(永远不会自己发出任何东西)。所以基本上是"read only"。
export function manageRequestGuideError(action$) {
return action$.ofType(REQUEST_GUIDE_FAILED)
.do(({error}) => {
console.log('Error',error)
})
.ignoreElements();
}
下一个也是最大的问题是您放置 catch
的位置。重要的是要了解使用 RxJS 意味着我们如何将 Observable 链接在一起——"operators" 基本上采用一个源和 return 另一个 Observable,后者将延迟对通过它们传输的数据应用一些操作。这与使用数组(例如 arr.map().filter()
)的函数式编程非常相似,但有两个主要区别:Observables 是惰性的并且它们有 time-dimension.
运算符的工作原理
所以考虑这个 Observable 链:
Observable.of(1, 2, 3)
.map(num => num.toString())
.filter(str => str !== '2');
.subscribe(value => console.log(value));
- 我们创建一个 Observable,当订阅时,它会同步发出 1、2、3。
- 我们将
map
运算符应用于该源,它创建了一个新的 Observable,当订阅时,它本身将订阅我们应用它的源:我们的 Observable 1、2、3。 - 然后我们应用
filter
运算符to the Observable returned by
map. As you might have guessed,
filterreturns a new Observable that, when subscribed to, will itself subscribe to the source we applied it to: our Observable of strings we mapped. Because that
map` Observable 本身被应用到一个源,然后它也会订阅它的源, 拉入第一个数字并开始地图 -> 过滤操作。
将这些中间 Observable 存储为变量可能会有所帮助,以揭开神秘面纱。
const source1: Observable<number> = Observable.of(1, 2, 3);
const source2: Observable<string> = source1.map(num => num.toString());
const result: Observable<string> = source2.filter(str => str !== '2');
内部 Observables
当我们使用像 mergeMap
、switchMap
、concatMap
这样的运算符时,我们是说我们想将每个值映射到另一个 "inner" Observable 的值将是在前一个内部 Observable 之后合并、切换或排队(concat)。它们有不同的重要区别,但如果您不熟悉它们,可以参考很多资源。
在您的例子中,我们使用的是 mergeMap
,它还有一个别名 flatMap
,这是函数式编程中更广为人知的术语。 mergeMap
将为您的投影函数提供每个值,并同时为您 return 订阅 Observable。每个内部 Observable 的值都合并在一起。
在函数式编程中,他们更常称此为扁平化,而不是合并。因此,首先在 Arrays
的上下文中考虑这个 merging/flattening 可能会再次有所帮助Array.prototype.map
[1, 3, 5].map(value => {
return [value, value + 1];
});
// [[1, 2], [3, 4], [5, 6]] Array<Array<number>>
这导致了一个由数字组成的数组 Array<Array<number>>
,但是如果我们想要一个单一的扁平化数组呢?输入 flatMap
.
Array.prototype.flatMap (stage 2 TC39 proposal)
[1, 3, 5].flatMap(value => {
return [value, value + 1];
});
// [1, 2, 3, 4, 5, 6] Array<number>
JavaScript 数组还正式有 flatMap
,但在撰写本文时它是 stage 2 TC39 proposal。它遵循与典型 flatMap
相同的语义:对于数组中的每个项目,将其映射到投影函数提供的另一个数组,然后将每个项目展平为一个新数组。
对于 Observables,它几乎是一样的,除了它们是惰性的并且有一个时间维度:
Observable.of(1, 3, 5).map(value => {
return Observable.of(value, value + 1);
});
// Observable.of(1, 2)..Observable.of(3, 4)..Observable.of(5, 6) | Observable<Observable<number>>
我们将每个数字映射到它们自己的两个数字的 Observable 中。所以 higher-order Observable Observable<Observable<number>>
可能不是我们想要的在大多数情况下。
Observable.of(1, 3, 5).flatMap(value => {
return Observable.of(value, value + 1);
});
// 1..2..3..4..5..6 | Observable<number>
现在我们只有所有数字的流。完美!
错误处理
结合我们对操作链接和 Observable 扁平化的理解,我们来谈谈错误处理。希望这本入门书能让下一部分更容易理解。
如果我们链式 Observables 中的任何一个抛出错误,它将以与值相同的方式在链中传播,但基本上是在它自己的 "channel" 中。所以如果我们有一个 Observable 链 a -> b -> c
并且在 a
中发生错误,它将被发送到 b
然后 c
。当每个 Observable 收到错误时,它可以以某种方式处理它,或者选择将它传递给任何订阅它的人。当它这样做时,该订阅将终止并且不再侦听来自其源的未来消息。
大多数运算符只是传递错误(同时终止),所以如果您没有使用像 catch
这样的特殊错误处理运算符,错误就会传播直到它到达您的观察者——您自己传递给的那个.subscribe(next, error, complete)
。如果您提供了该错误处理程序,它将被调用,如果没有,它将作为正常的 JavaScript 异常重新抛出。
为了最终得到你的代码,让我们从头开始;我认为你真正想要的是:
function getGuide(id) {
const promise = fetchJsonp(`${API_URL}/guide/${id}/jsonp`)
.then(res => res.json());
return Observable.from(promise);
}
export function requestGuide(action$) {
return action$.ofType(REQUEST_GUIDE)
.mergeMap(({id}) =>
getGuide(id)
.mergeMap(json => Observable.of(
requestGuideFulfilled(json),
requestGameTask(json)
))
.catch(error => Observable.of(
requestGuideFailed(error)
))
)
}
现在我们来分解一下。
Promise 与 Observable
您首先会看到我将您的 fetchJsonp
提取到 getGuide
函数中。您也可以将这段代码放在史诗中,但是如果您决定测试,将它分开将使您更容易模拟它。
我尽快将 Promise 包装在 Observable 中。主要是因为如果我们选择使用 RxJS,我们应该选择 all-in,尤其是为了防止以后出现混淆。例如Promise 和 Observable 实例都有 catch
方法,因此如果您开始混合使用两者,很容易导致错误。
理想情况下我们会完全使用 Observables 而不是 Promises,因为 Promises 不能被取消(所以你不能取消实际的 AJAX 请求 + JSON 解析本身),尽管如果你把它包装在一个 Observable 并在 promise 解析之前取消订阅,Observable 将正确地忽略 promise 稍后解析或拒绝的内容。
发出多个动作?
它不是 100% 清楚,但看起来你打算发出两个动作以响应成功取回 JSON。您之前的代码实际上将 JSON 映射到 requestGuideFulfilled()
操作,但是下一个运算符将该操作映射到 requestGameTask()
(它不接收 JSON,它接收requestGuideFulfilled()
行动)。记得上面,关于运算符如何成为 Observables 链,值流经它们。
要解决这个问题,我们需要思考"in streams"。我们的 getGuide()
Observable 将发出一个值,即 JSON。给定单个 (1) 值,我们希望将其映射到多个其他值,在本例中为两个操作。所以我们要改造one-to-many。我们需要使用 mergeMap
、switchMap
或 concatMap
之一。在这种情况下,由于我们的 getGuide()
永远不会发出超过一项,所以所有这三个运算符都会有相同的结果,但了解它们很重要,因为它通常 很重要 所以记住这一点!在这种情况下,我们只使用 mergeMap
。
.mergeMap(json => Observable.of(
requestGuideFulfilled(json),
requestGameTask(json)
))
Observable.of
支持任意数量的参数,并将按顺序发出每个参数。
捕获错误
因为我们的 Observable 链是......嗯..链 hehe 值在它们之间通过管道传输。正如我们在上面了解到的那样,由于这个 where 你在这些链中放置错误处理很重要。这其实和传统的异常处理,甚至是 promises 的错误处理没有太大区别,但是 Promises 没有 "operators",所以人们通常不会 运行 陷入这种困惑。
catch
运算符是最常见的,它与 catch
Promise 非常相似,除了 你必须 return 一个你想要的值的 Observable ,而不是值本身。 Observable.of
在这里很常见,因为大多数情况下我们只想按顺序发出一个或多个项目。
.catch(error => Observable.of(
requestGuideFailed(error)
))
每当我们应用此运算符的源发出错误时,它都会捕获它并发出 requestGuideFailed(error)
然后 complete()
.
因为它发出错误操作,我们应用于此 .catch()
** 的结果的任何运算符也可以对我们的 catch
发出的值进行操作。
getJsonSomehow()
.catch(error => Observable.of(
someErrorAction(error)
))
.map(json => {
// might be the JSON, but also might be the
// someErrorAction() action!
return someSuccessAction();
})
虽然不是 redux-observable 独有的(因为 redux-observable 主要只是一个小型库和一个约定,使用 RxJS)你会经常看到 Epics 遵循类似的模式。
- 侦听特定操作
- 然后将该动作合并或切换到执行副作用的内部 Observable 中
- 当副作用成功时,我们
map
将其作为成功操作 - 以防出错,我们在
mergeMap
/switchMap
中放置一个catch
,但最常见的是在内链的末尾,o 我们发出的任何动作都不会意外改变。
您有望从 redux-observable 文档中识别出一般模式:
function exampleEpic(action$) {
return action$.ofType(EXAMPLE)
.mergeMap(action =>
getExample(action.id)
.map(resp => exampleSuccess(resp))
.catch(resp => Observable.of(
exampleFailure(resp)
))
);
}
将这些知识应用到我们之前的工作中:
getGuide(id)
.mergeMap(json => Observable.of(
requestGuideFulfilled(json),
requestGameTask(json)
))
.catch(error => Observable.of(
requestGuideFailed(error)
))
我想就是这样。
呸!抱歉,那是 long-winded。你完全有可能知道其中的一些或全部,所以如果我在宣讲合唱团,请原谅我!我开始写一些简短的东西,但在澄清之后不断添加澄清。哈哈
如果您正在苦苦挣扎,请务必确保使用 RxJS 和 redux-observable(或任何复杂的中间件)是您的应用程序所必需的复杂性。