我正在使用Angular 9和rxjs 6,并且我正在尝试获取节点列表:
NodeService.ts
class EventListener extends StatefulWidget {
@override
_EventListenerState createState() => _EventListenerState();
}
class _EventListenerState extends State<EventListener> {
Offset offset = Offset(0, 0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EventListener"),
),
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
color: Colors.red,
height: 200,
),
Container(
color: Colors.teal,
height: 300,
),
Container(
color: Colors.orange,
height: 400,
)
],
),
),
Container(
color: Colors.cyan,
width: double.infinity,
height: 400,
alignment: Alignment.center,
child: SizedBox(
width: 100,
height: 100,
child: Transform.translate(
offset: offset,
child: FlatButton(
color: Colors.orange,
onPressed: () {
setState(() {
offset += Offset(50, 50);
});
print('click !');
},
child: Text("translate"),
),
),
),
)
],
),
);
}
}
节点实体:
short _type; // file type
short _size;
int _reserved;
int _offset;
int _info_size;
int _width;
int _height;
short _planes;
short _bpp;
int _compression;
int _imagesize;
int _xresolution;
int _yresolution;
int _colours;
int _impcolours;
nodes.component.ts:
public getList(): Observable<Nodes[]> { return this.http.get<Nodes[]>(URL); }
=>默认情况下,node.site = null,所以我使用node.site_id在subscription方法中获取完整的“ Site”对象。 但是我几乎有6000次呼叫“ siteService.getSiteById()”,并且出现类似错误的消息:资源不足。
您有更好的方法吗
谢谢
答案 0 :(得分:0)
如果您需要进行6000个单独的HTTP调用,则可能必须修改后端以在单个请求中返回所有信息。同时,您可以尝试使用带有switchMap
和concatMap
函数的from
的RxJS of
运算符来顺序执行请求。
import { of, from } from 'rxjs';
import { switchMap, concatMap, finalize } from 'rxjs/operators';
public getAllNodes() {
this.dataSource.data = [];
let sites = [];
this.nodeService.getList().pipe(
switchMap(nodes => {
let requests = [];
this.dataSource.data = nodes;
nodes.forEach(node => requests.push(this.siteService.getSiteById(node.site_id)));
return from(requests);
}),
concatMap(request => of(request)),
finalize(() => {
this.dataSource.data.forEach((node, index) => node.site = sites[index]);
})
).subscribe(
site => {
sites.push(site);
},
error => {
// handle error
}
);
}
现在将依次执行6000个请求,所以它太慢了。
mergeMap
如Will Alexander在评论中所建议,您可以使用RxJS mergeMap
运算符来处理并发请求。但我建议您将其设置为小于6,因为大多数浏览器对同时发送到唯一域的请求数量都有严格的限制。
因此您可以替换
concatMap(request => of(request))
使用
mergeMap(request => of(request), null, 5) // <-- 5 concurrent requests
答案 1 :(得分:0)
遵循以下原则:
public getAllNodes() {
return this.nodeService.getList().pipe(
// emit all elements of the array separately
map(nodes => from(nodes)),
// subscribe to each Observable in turn
// allow 5 concurrent requests
mergeMap(node$ => node$, null, 5).pipe(
// for each node, get the corresponding site, and emit the full object
concatMap(
node => this.siteService.getSiteById(node.site_id),
(node, site) => { ...node, site })
),
// when Observable completes, emit all emissions as an Array
toArray()
);
}