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
    的变量传递给每个camera函数,但这只是为了让console.log()能够清楚地显示camera正在做什么
  • 我没有使用
    redux observable
    做任何事情,而是将它保持在普通的
    rxjs
  • 我用
    concat()
    将拍摄照片转换为一个可观察的序列,而不是让它保持一系列承诺——这不是必要的,只是一种不同的方法
  • 我将摄像机作为单独的观察对象(
    cameraA$
    cameraB$
    ),但这也可以通过摄像机阵列来完成
请随意使用叉子,并将其更改为更接近您要查找的内容

以下是StackBlitz中的内容:

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();

我希望这能有所帮助。

你的问题可以归结为并行执行一些观察值,按顺序执行其他观察值,并根据承诺创建观察值

  • 要并行执行多个观测值,请使用:
    • ,如果您只希望在所有摄影机操作完成后发射最终可观察对象
    • ,如果希望在每次单个摄影机操作成功时发射最终可见光
  • 用于按顺序执行多个观察值

  • 用于根据承诺创建可观察的,但不要立即执行承诺

  • 那么你必须

    • 构造一个要按顺序执行的观察值数组。
      (单个摄影机每个角度的动作)
    • 构造一个要并行执行的可观察对象数组。
      (每个摄影机的摄影机操作)
    这可能是普通RxJS中的代码

    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