内容简介:原文:译者:日志记录并不是一件让人兴奋的事。
原文: Debugging RxJS, Part 2: Logging
译者: Ice Panpan ;校验者:暂无
日志记录并不是一件让人兴奋的事。
然而,这是获得足够的信息来推理问题最直接的方法,而不需要去猜测。它通常是调试 RxJS 代码的首选方法。这是这个系列文章的第二篇,专注于使用日志记录来解决实际问题。在第一篇 调试 Rxjs(一):工具 中,主要介绍的是 rxjs-spy 。在本文中,我将展示如何使用 rxjs-spy 以最小的影响来获取详细并有针对性的信息。
让我们看一个使用 rxjs 和 rxjs-spy UMD捆绑的简单案例:
RxSpy.spy();
RxSpy.log(/user-.+/);
RxSpy.log('users');
const names = ['benlesh', 'kwonoj', 'staltz'];
const users = Rx.Observable.forkJoin(...names.map(name =>
Rx.Observable
.ajax
.getJSON(`https://api.github.com/users/${name}`)
.tag(`user-${name}`)
))
.tag('users');
users.subscribe();
复制代码
该示例使用 forkJoin 组合了一个用来发射出GitHub用户数组的 Observable 。
rxjs-spy 使用 tag 操作符来标记 Observable ,并且仅仅通过字符串来给 Observable 注释。这个示例在组合 Observable 之前,首先启用监听功能,并配置了哪些 Observable 要被记录——匹配 /user-.+/ 的正则表达式或者带有 users 标签的那些 Observable 。
这个示例的控制台输出如下:
除了 Observable 的 next 和 complete 的通知之外,记录的输出还包括订阅和取消订阅的通知。它显示了发生的一切:
- 对组合的
Observable的订阅影响的每一个用户API请求的Observable的并行订阅; - 请求以任意顺序完成;
-
Observable全部完成; - 并且在全部完成后取消对组合
Observable的订阅。
每个记录的通知还包括有关接受通知的订阅者的信息——包括订阅者具有的订阅量以及 subscribe 调用的堆栈痕迹:
堆栈痕迹指的是 subscribe 调用的根——即影响订阅者对 Observable 订阅的显式调用。因此,用户请求的 Observable 的堆栈痕迹也参考了 medium.js 中的 subscribe 调用:
当我调试时,我发现知道调用 subscribe 的实际的根位置比知道组合 Observable 中某个 subscribe 的位置更有用。
现在让我们看一个现实中实际的问题。
在编写 redux-observable epics 或 ngrx effects 时,我看到几个开发人员类似的代码:
import { Observable } from 'rxjs/Observable';
import { ajax } from 'rxjs/observable/dom/ajax';
const getRepos = action$ =>
action$.ofType('REPOS_REQUEST')
.map(action => action.payload.user)
.switchMap(user => ajax.getJSON(`https://api.notgithub.com/users/${user}/repos`))
.map(repos => { type: 'REPOS_RESPONSE', payload: { repos } })
.catch(error => Observable.of({ type: 'REPOS_ERROR' }))
.tag('getRepos');
复制代码
乍一看,这看上去还不错。大部分时间它都可以正常工作,它是那种可以偷偷混过单元测试的bug。
问题是,它有时会停止工作,特别是在一个错误的动作发生之后。
记录显示正在发生的事:
在错误的动作被发射出去之后,看到 redux-observalbe 基础结构从epic中解除订阅的 Observable 完成了。该文档的 catch 解释了为什么出现这种情况。
无论 selector 返回了什么样的 Observable ,都将连在 Observable 链后面。
在这个epic中, catch 完成后返回的 Observable 也看到了epic的完成。
解决的方案是将 map 和 catch 移到 switchMap 中,像下面这样:
import { Observable } from 'rxjs/Observable';
import { ajax } from 'rxjs/observable/dom/ajax';
const getRepos = action$ =>
action$.ofType('REPOS_REQUEST')
.map(action => action.payload.user)
.switchMap(user => ajax
.getJSON(`https://api.notgithub.com/users/${user}/repos`)
.map(repos => { type: 'REPOS_RESPONSE', payload: { repos } })
.catch(error => Observable.of({ type: 'REPOS_ERROR' }))
)
.tag('getRepos');
复制代码
这个epic将不再完成,并继续发送错误动作:
在这两个示例中,需要对正在调试的代码进行的唯一修改是添加了一些标记注释。
注释的影响很小,一旦添加,我倾向于将它们留在代码中。标签运算符可以独立于诊断 rxjs-spy 使用——使用 rxjs-spy/add/operator/tag 或直接导入 rxjs-spy/operator/tag ,因此保留标记的开销很小。
可以使用正则表达式配置记录器,这可以产生许多可能的标记方法。例如,使用复合标记,例如 github/users 和 github/repos 将允许您为所有被标记后存储在存储库里的 github Observable 启用日志记录。
记录并不令人兴奋,但可以从记录的输出中收集的信息通常可以节省大量时间。采用灵活的标记方法可以进一步减少处理与日志记录相关的代码所花费的时间。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- CVE-2018-4990漏洞调试分析记录
- DfMarshal系列漏洞CVE-2018-8550调试记录
- 【IntelliJ IDEA】Debug调试的使用记录
- GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)
- GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(下)
- iOS常用调试方法:断点调试
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JS 压缩/解压工具
在线压缩/解压 JS 代码
UNIX 时间戳转换
UNIX 时间戳转换