我有一个函数和一个验证辅助函数,可以将 tsv 文件作为字符串读取。我正在尝试通过使用 rxjs 执行同步任务来练习我的响应式(Reactive)编程。我知道这可能不是它的完美用例,但我知道它应该是可能的。
这是最简单形式的伪代码:
public readTsv(tsv: string): Observable<TsvAsObject> {
if (!tsv || tsv.length < 1) {
return Observable.throw('null or empty tsv file passed');
}
// check tsv headers
this.validHeadersObs(tsv.split('\n')[0]) // pass the first line of the tsv string
.filter(valid => valid === false)
.subscribe(() => {
return Observable.throw('invalid tsv headers')
});
// omitted logic that processes the tsv and then returns it as an observable
return Observable.of(tsvAsObject);
}
我已经测试了我的 validHeaders() 函数,我知道它可以工作。它返回检查每个列标题的 bool 值流。一旦一对标题不匹配,它将返回一个 Observable.of(false):
private validHeadersObs(headerLine: string): Observable<boolean> {
const headers$ = Observable.from(headerLine.split('\t'));
const validHeaders = ['columnName1', 'columnName2', 'columnName3'];
return headers$
.mergeMap((value, index) => Observable.of(value === validHeaders[index]));
}
问题是 readTsv() 不返回
Observable.throw('invalid tsv headers')
因为我不确定如何从订阅中提前从函数中返回。有没有办法从箭头函数内部“双重返回”?
最佳答案
好的,看看你要做什么,我看到了一个危险信号:在一个要返回一个可观察对象的函数中,可能不应该有 subscribe
调用,除非它在另一个 Observable 的主体内。
你要做的是:
validHeadersObs
调用您要执行的下一个操作。这实际上与你需要对 promise 做的事情没有什么不同(认为 validate.then(returnAthing)
, validate.map(returnAthing)
在这种情况下并没有太大不同)。 您当前代码中的问题是您开始这项工作的是
订阅,它是异步的,所以它不会返回,然后你继续
返回可观察到的“快乐路径”。如果返回“幸福路径”
observable 取决于您的验证调用的异步反馈,
你需要把它锁起来。
(小注意,如果任何 tsv 处理逻辑碰巧是异步的,你会想要使用
switchMap
而不是 map
)这应该这样做:
public readTsv(tsv: string): Observable<TsvAsObject> {
if (!tsv || tsv.length < 1) {
// throw an error as soon as you can
throw new TypeError('null or empty tsv file passed');
}
// check tsv headers
return this.validHeadersObs(tsv.split('\n')[0])
.map(valid => {
if (!valid) {
throw new Error('invalid tsv headers');
}
// omitted logic that processes the tsv here
return tsvAsObject
});
}
关于error-handling - 从返回可观察对象的函数中提前返回错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46090924/