RxJS-控制多个并行执行
我有一个场景,我必须控制多个云台摄像机,以拍摄多个角度的照片。因此,例如:RxJS-控制多个并行执行,rxjs,redux-observable,Rxjs,Redux Observable,我有一个场景,我必须控制多个云台摄像机,以拍摄多个角度的照片。因此,例如: 摄像机A将采用角度A1,A2,A3 摄像机B将采用角度B1,B2,B3,B4 将相机移动到正确的角度,拍摄图像并上传图像,是返回承诺的异步函数。 移动摄像机(角度) captureImage() uploadImage() 摄像机必须并行工作,但每个摄像机所拍摄的角度必须按顺序进行 我觉得RxJS可以很容易地解决这个问题,但我正在努力把它们拼凑起来。我所能做的最好的事情,就是下面的解决方案,不知何故,它让相机按顺序相互处
摄像机A
将采用角度A1
,A2
,A3
摄像机B
将采用角度B1
,B2
,B3
,B4
将相机移动到正确的角度,拍摄图像并上传图像,是返回承诺的异步函数。移动摄像机(角度)
captureImage()
uploadImage()
摄像机必须并行工作,但每个摄像机所拍摄的角度必须按顺序进行
我觉得RxJS可以很容易地解决这个问题,但我正在努力把它们拼凑起来。我所能做的最好的事情,就是下面的解决方案,不知何故,它让相机按顺序相互处理。请注意,我使用的是redux observable
,下面的代码是我在普通RxJS中所能使用的最好的代码。请原谅我的RXJ
const angles={
“摄像机A”:[“A1”、“A2”、“A3”],
“摄像机B”:[“B1”、“B2”、“B3”、“B4”],
}
常量摄影机=of(['摄影机A'、'摄影机B']);
const cameraRun=cameras.pipe(
合并地图(相机=>{
//在redux observable中,我可以在这里返回一个数组
返回(角度[摄像机]);
} )
);
摄像管(
concatMap(角度=>{
返回移动摄影机(角度)
。然后(()=>captureImage())
。然后(()=>uploadImage())
。然后(()=>console.log('Image success');
} )
)
对于那些知道“可观察的重复次数”的人,我有三部史诗:RUN\u CAMERA\u SET\u例程
-运行mergeMap
RUN\u CAMERA\u例程
-在mergeMap
CAPTURE\u IMAGE
-在一个concatMap
我最初的想法是,CAPTURE\u IMAGE
将由于mergeMap
生成流而“分组”,但我错了。对于所有摄像机来说,CAPTURE\u IMAGE
似乎仍然是一个从每个角度排队的流
任何指点都会很有帮助。我来试试这个。我提出了一个解决方案来表达我的想法。单击控制台,然后单击按钮开始新的运行 有关此解决方案的一些要点:
- 我只使用
点击鼠标启动新的运行,这对解决方案并不重要start$
- 我用不同的超时模拟了三个摄像头承诺函数,只是为了显示事情是如何按顺序执行的,但是两个摄像头是如何并行的
- 我还将
的变量传递给每个camera函数,但这只是为了让console.log()能够清楚地显示camera正在做什么camera
- 我没有使用
做任何事情,而是将它保持在普通的redux observable
rxjs
- 我用
将拍摄照片转换为一个可观察的序列,而不是让它保持一系列承诺——这不是必要的,只是一种不同的方法concat()
- 我将摄像机作为单独的观察对象(
和cameraA$
),但这也可以通过摄像机阵列来完成cameraB$
import { mergeMap, concatMap, tap } from 'rxjs/operators';
import { fromEvent, from, concat, merge, defer } from 'rxjs';
const moveCamera = (camera, angle) => new Promise(
(resolve, reject) => {
setTimeout(() => {
console.log(`moved: ${camera} angle: ${angle}`);
resolve();
}, 1000) }
);
const captureImage = (camera) => new Promise(
(resolve, reject) => {
setTimeout(() => {
console.log(`${camera} captured image.`);
resolve();
}, 100) }
);
const uploadImage = (camera) => new Promise(
(resolve, reject) => {
setTimeout(() => {
console.log(`${camera} uploaded image.`);
resolve();
}, 2000) }
);
const start$ = fromEvent(document.getElementById('start'), 'click');
const takeAPhoto$ = (camera, angle) => concat(
defer(() => moveCamera(camera, angle)),
defer(() => captureImage(camera)),
defer(() => uploadImage(camera))
);
const cameraA$ = from(['A1', 'A2', 'A3']).pipe(
concatMap(angle => takeAPhoto$('Camera A', angle))
);
const cameraB$ = from(['B1', 'B2', 'B3', 'B4']).pipe(
concatMap(angle => takeAPhoto$('Camera B', angle))
);
start$.pipe(
tap(() => console.log('\n\nstart new run')),
mergeMap(() => merge(cameraA$, cameraB$)),
).subscribe();
我希望这能有所帮助。你的问题可以归结为并行执行一些观察值,按顺序执行其他观察值,并根据承诺创建观察值
- ,如果您只希望在所有摄影机操作完成后发射最终可观察对象
- ,如果希望在每次单个摄影机操作成功时发射最终可见光
- 构造一个要按顺序执行的观察值数组。
(单个摄影机每个角度的动作) - 构造一个要并行执行的可观察对象数组。
(每个摄影机的摄影机操作)
import{concat,forkJoin,merge,defer}来自'rxjs';
常量摄影机=['摄影机A'、'摄影机B'];
常量摄影机角度={
“摄像机A:['A1'、'A2'、'A3'],
“摄像机B”:['B1','B2','B3','B4']
}
//执行由多个部分组成的摄影机动作。回报一个承诺。
//摄像机:例如“摄像机A”,角度:例如“A1”
常量doCameraAction=(摄影机,角度)=>moveCamera(角度)
。然后(()=>captureImage())
。然后(()=>uploadImage())
。然后(()=>console.log('Image success');
//创建按顺序执行多个摄影机操作的可观察对象。
//摄像机:例如“摄像机A”,角度:例如。['A1','A2','A3']
const getCameraActionSequence$=(摄影机,角度)=>concat(
//我们希望按顺序执行的观察值数组
…angles.map(角度=>defer(()=>doCameraAction(摄影机,角度)))
);
//一个可观察的将并行执行多个摄影机动作序列的对象
常量multiCameraActions$=forkJoin(
//我们希望并行执行的观察值数组
map(camera=>getCameraActionSequence$(camera,CameraAngels[camera]))
);
谢谢。与@fridoo的答案类似。之所以选择这个答案,是因为代码的冗长解释了这个想法。嗨,你能看看这个吗,我不知道为什么这个不起作用。我想动态添加相机。非常好地提到了
forkJoin
和简洁的代码。如果我能接受两个答案,我也会接受这个答案。我现在了解到,您可以在lat的数组中动态排队defer