我正在尝试构建一些代码,使用扩展运算符对结果集进行分页,直到获取一定数量的资源为止。这是我到目前为止所拥有的(删除了实际的异步调用逻辑):
import { Observable } from 'rxjs';
const items = [
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
[21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
];
const call = () => {
console.log('#call');
const batch = items.shift();
if (batch) {
return Observable.of(batch).delay(100);
}
return Observable.empty();
}
const o$ = call().expand((values) => {
console.log('expansion');
return call();
}).flatMap((val: any) => val);
const log = (prefix: string) => (...args: any[]) => console.log(prefix, ...args);
o$.take(9).subscribe(log('next'), log('error'), log('complete'));
输出与我想要的不同:
#call
takeWhile.ts:26 next 1
takeWhile.ts:26 next 2
takeWhile.ts:26 next 3
takeWhile.ts:26 next 4
takeWhile.ts:26 next 5
takeWhile.ts:26 next 6
takeWhile.ts:26 next 7
takeWhile.ts:26 next 8
takeWhile.ts:26 next 9
takeWhile.ts:26 complete
takeWhile.ts:22 expansion
takeWhile.ts:10 #call
我得到了我的 9 个项目,这是我使用 take
请求的,然后流完成,但发生了一次额外的扩展,模拟异步 API 再次被调用。
有什么方法可以让我的代码不那么贪婪并且不开始另一个递归迭代吗?
最佳答案
您看到的行为是预期的:expand
在 take
之前被调用,所以
- 我们得到第一个值
- expand执行并调用
- 然后立即取消订阅整个 observable
因此,您需要使递归调用异步,以便让 take
在调用 之前取消订阅。最简单的修复似乎是用 return timer(4).map(call);
替换 return call();
(甚至 return defer( call);
,这神奇地起作用了 :/)。
所以一般来说,你需要做一个“暂停”/“间隙”让限制器启动并取消订阅。
希望对你有帮助
关于angular - 展开运算符执行次数超过预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56344272/