Javascript RxJs:通过API递归分页并从列表中查找值
我使用的是RXJSV6.4.0。我试图通过一个API分页,搜索一个非常特定的通道,其中的名称等于“development”。我使用Javascript RxJs:通过API递归分页并从列表中查找值,javascript,rxjs,operators,expand,pagination,Javascript,Rxjs,Operators,Expand,Pagination,我使用的是RXJSV6.4.0。我试图通过一个API分页,搜索一个非常特定的通道,其中的名称等于“development”。我使用expand递归调用API并获取新页面。最终结果为我提供了通道的串联列表。然后我过滤掉所有名称不等于“开发”的通道。然而,我得到了一个错误:TypeError:您在需要流的地方提供了“undefined”。您可以提供一个可观察的、承诺的、数组的或可观察的。 const Rx = require('rxjs') const Rx2 = require('rxjs/ope
expand
递归调用API并获取新页面。最终结果为我提供了通道的串联列表。然后我过滤掉所有名称不等于“开发”的通道。然而,我得到了一个错误:TypeError:您在需要流的地方提供了“undefined”。您可以提供一个可观察的、承诺的、数组的或可观察的。
const Rx = require('rxjs')
const Rx2 = require('rxjs/operators')
const getChannel = (cursor) => {
return this.service.getData(`${url}?cursor=${cursor || ''}`)
.pipe(Rx2.map(resp => JSON.parse(resp.body)))
.pipe(Rx2.expand(body => { // recurse the api until no more cursors
return body.response_metadata &&
body.response_metadata.next_cursor ?
getChannel(body.response_metadata.next_cursor) : Rx.EMPTY
}))
.pipe(Rx2.pluck('channels'))
.pipe(Rx2.mergeAll()) // flattens array
.pipe(Rx2.filter(c => {
console.log('finding', c.name === 'development')
return c.name === 'development'
}))
}
find
回调应返回布尔值,而不是可观察值。例如
find(c=>c.name==='development')
更新
这是你的一个修改过的例子。我已经移除了发电机,因为它们比我们的案子需要的更复杂
const{of,EMPTY,throwError}=rxjs;
const{filter,tap,expand,pull,mergeAll}=rxjs.operators;
常数数据=
[{channels:[{id:123,name:'test'},{id:4,name:'hello'}],游标:1}
,{channels:[{id:1,name:'world'},{id:2,name:'knows'}],游标:2}
,{channels:[{id:3,名称:'react'},{id:5,名称:'devcap'}],游标:false}
];
函数getChannel(){
返回getBlock()
.烟斗(
展开(x=>x.cursor?getBlock(x.cursor):空),
弹拨(“通道”),
mergeAll(),
过滤器(c=>c.name=='devcap')
)
}
getChannel()。订阅({
下一步:console.log,
错误:console.error
});
函数getBlock(索引=0){
如果(索引>=DATA.length){
投掷者(“出界”);
}
返回(数据[索引]);
}
更新2
由于仅通过getChannel()
执行递归,您的解决方案无法工作。当您执行展开时
——通过getChannel()
运行另一个循环。这意味着您对每个递归获取的值运行两次pull mergeAll filter
chain!两次拨弄和奉承它会给你未定义的
——因此是错误的
在你的操场上——试着把这个代码分开
让getValue=()=>{
const next=gen.next();
如果(!next | |!next.value){返回空;}
返回next.value;
}
并在展开中使用它,如下所示:
让getChannel=()=>{
返回getValue()
.烟斗(
展开(正文=>{
return body.cursor?getValue():空
}),
弹拨(“通道”),
mergeAll(),
过滤器(c=>c.name=='devcap'),
)
}
请告诉我这是否是您正在寻找的功能
我已更改为布尔值,并将
find
更改为filter
。我得到了一个错误:您提供了一个“未定义”的预期流。您可以提供一个可观察的、承诺的、数组的或可观察的。@courtyen,很难说,不过这个错误似乎来自expand()
。当您完成递归时--尝试返回,而不是未定义的我在我的扩展中使用三元值更新了您的注释。不幸的是,我仍然收到与上面相同的错误。从日志中,我看到在我点击最后一个光标之前发出了错误。感谢Kos对此的帮助。给我一些时间,我会提供一个游乐场。我没有编辑答案来回应。我编辑它是因为我和他一起工作,虽然他解决了问题,但他没有完全清楚地回答问题。
const {
of,
EMPTY
} = rxjs;
const {
filter,
tap,
expand,
take,
pluck,
concatAll,
flatMap,
first
} = rxjs.operators;
function* apiResponses() {
yield of({channels: [{id: 123, name: 'test'}, {id:4, name: 'hello'}], cursor: 1});
yield of({channels:[{id: 3, name: 'react'}, {id: 5, name: 'devcap'}], cursor:3});
yield of({channels:[{id: 1, name: 'world'}, {id: 2, name: 'knows'}], cursor: 2});
yield of({channels:[{id: 4, name: 'react'}, {id: 6, name: 'devcap'}], cursor:4});
}
let gen = apiResponses();
function getChannel() {
return gen.next().value // simulate api call
.pipe(
expand(body => {
return body.cursor ? gen.next().value : EMPTY
}),
pluck('channels'),
flatMap(channels => {
const filtered = channels.filter(channel => channel.name === 'devcap')
if(filtered.length) {
return filtered;
}
return EMPTY;
}),
first()
);
}
getChannel().subscribe(data => {
console.log('DATA!! ', data)
}, e => {
console.log('ERROR', e)
throw e
})