我猜这应该有点容易实现,但我遇到了麻烦(概念上,我猜)找出解决方法。
我所拥有的是一个返回JSON对象数组的API。我需要逐步浏览这些对象,并为每个对象进行另一个AJAX调用。问题是处理每个AJAX调用的系统一次只能处理两个活动调用(因为它是一个CPU密集型任务,可以挂钩到桌面应用程序中)。
我想知道如何使用RxJS(使用版本5或4)实现此目的?
编辑:此外,是否可以同时运行一系列步骤。即。
Downloading File: 1
Processing File: 1
Converting File: 1
Uploading File: 1
Downloading File: 2
Processing File: 2
Converting File: 2
Uploading File: 2
Downloading File: 3
Processing File: 3
Converting File: 3
Uploading File: 3
我尝试过这样的事情:
Rx.Observable.fromPromise(start())
.concatMap(arr => Rx.Observable.from(arr))
.concatMap(x => downloadFile(x))
.concatMap((entry) => processFile(entry))
.concatMap((entry) => convertFile(entry))
.concatMap((entry) => UploadFile(entry))
.subscribe(
data => console.log('data', new Date().getTime(), data),
error => logger.warn('err', error),
complete => logger.info('complete')
);
然而,这似乎不起作用。例如,downloadFile不等待processFile,convertFile和uploadFile全部完成,而是下一个将在前一个完成后再次运行。
答案 0 :(得分:4)
如果您希望请求序列与此
完全相同,则有两种方法Downloading File: 1
Processing File: 1
Converting File: 1
Uploading File: 1
Downloading File: 2
Processing File: 2
...
你需要解决单个concatMap方法中的所有promise,比如
Rx.Observable.fromPromise(getJSONOfAjaxRequests())
.flatMap(function(x) { return x;})
.concatMap(function(item) {
return downloadFile(item)
.then(processFile)
.then(convertFile);
})
.subscribe(function(data) {
console.log(data);
});
在此处查看工作插件:https://plnkr.co/edit/iugdlC2PpW3NeNF2yLzS?p=preview 这样,只有在前一个完成时才会发送新的ajax调用。
另一种方法是允许文件并行发送请求,但操作“下载,处理,转换,上传”将按顺序进行。为此你可以通过
来实现它Rx.Observable.fromPromise(getJSONOfAjaxRequests())
.flatMap(function(x) { return x;})
.merge(2) // in case maximum concurrency required is 2
.concatMap(function(item) {
return downloadFile(item);
})
.concatMap(function(item) {
return processFile(item);
})
.concatMap(function(item) {
return convertFile(item)
})
.subscribe(function(data) {
//console.log(data);
});
请参阅此处的plunkr:https://plnkr.co/edit/mkDj6Q7lt72jZKQk8r0p?p=preview
答案 1 :(得分:3)
您可以将merge
运算符与maxConcurrency
重载(Rxjs v4)一起使用,如下所示:
Rx.Observable.fromArray(aJSONs)
.map (function (JSONObject) {
return ajaxRequest(JSONObject) // that would be an observable (or a promise)
})
.merge(2)
您可以在以下位置查看其他使用示例:
官方文件:
答案 2 :(得分:1)
这样的事情怎么样?您可以使用from
将数组拆分为一口大小的块,然后使用concatMap
逐个处理它们。
function getArr() {
return Rx.Observable.of([1, 2, 3, 4, 5, 6, 7, 8]);
}
function processElement(element) {
return Rx.Observable.of(element)
.delay(500);
}
getArr()
.concatMap(arr => {
return Rx.Observable.from(arr);
})
.concatMap(element => {
return processElement(element);
})
.subscribe(res => {
console.log(res);
});
答案 3 :(得分:0)
旧帖子,但我相信这可以解决问题,对于控制台日志,我们可以使用tap。注释编辑器可能会遇到intellisense错误,因为from期望使用数组,但是代码应该可以工作。
from(start()).pipe(
switchMap(files => from(files).pipe(
switchMap(file => from(downloadFile(file)).pipe(
map(_ => ({file: file, downloaded: true}))
)),
switchMap(attr => from(processFile(attr.file)).pipe(
map(_ => ({...attr, downloaded: true}))
)),
switchMap(attr => from(convertFile(attr.file)).pipe(
map(_ => ({...attr, converted: true}))
)),
switchMap(attr => from(uploadFile(attr.file)).pipe(
map(_ => ({...attr, uploaded: true}))
))
))
).subscribe(_ => {})