【问题标题】:Expand operator executing more times than expected扩展运算符执行次数超出预期
【发布时间】:2019-10-14 02:29:55
【问题描述】:

我正在尝试构建一些代码,使用扩展运算符对结果集进行分页,并一直这样做直到获取了一定数量的资源。这是我到目前为止所拥有的(删除了实际的异步调用逻辑):

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。

有什么方法可以让我的代码不那么贪婪,并且不会开始另一个递归迭代?

【问题讨论】:

  • flatMap 有什么用?您想在每次下一次调用时收到包含 10 个项目的列表,还是希望每次下一次调用都只包含多维数组中的一项?
  • 我更愿意在 Take 操作员级别处理扁平项目。理想情况下应该仍然是一个请求,没有不必要的请求。

标签: angular typescript rxjs reactive-programming


【解决方案1】:

您看到的行为是预期的:expandtake 之前被调用,所以

  • 我们得到第一个值
  • 执行expand 并进行调用
  • 然后整个 observable 立即取消订阅

因此,您需要使递归调用异步,以让take 在调用之前取消订阅。最简单的解决方法似乎是将return call(); 替换为return timer(4).map(call);(甚至是return defer(call);,这很神奇:/)。

See this example in action

所以一般来说,你需要做一个“暂停”/“间隙”让限制器启动和取消订阅。

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 2016-04-07
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 2023-01-31
    • 1970-01-01
    相关资源
    最近更新 更多