Javascript rxjs相当于使用';返回';;

Javascript rxjs相当于使用';返回';;,javascript,typescript,rxjs,Javascript,Typescript,Rxjs,我想实现下面类似的东西(如果使用承诺,它们很容易实现) 如果我使用可观察的东西而不是承诺,我不知道如何做到这一点,但这是我迄今为止尝试过的方法 doSomething(sID){ let student; let teacher; service.getStudent(sID).pipe( switchMap(studentR=>{ student = studentR; return service.getTeacher(stude

我想实现下面类似的东西(如果使用承诺,它们很容易实现)

如果我使用可观察的东西而不是承诺,我不知道如何做到这一点,但这是我迄今为止尝试过的方法

doSomething(sID){
  let student;
  let teacher;
  service.getStudent(sID).pipe(
      switchMap(studentR=>{
        student = studentR;
        return service.getTeacher(student.TeacherID);
      }),
      switchMap(teacherR=>{
        teacher = teacherR;
        if(!teacher.Active){
            return of(null);
        }else{
            return service.teacherSomething(teacher);
        }
      }),
      swicthMap(teacherSomethingResponse=>{
          if(teacherSomethingResponse==null){
              return of(null);
          }else{
            return service.studentSomething(student);
          }
      })
  }).subscribe();

}

正如您所看到的,我的rxjs版本与promise版本相比似乎太长了,我觉得我做得不对。

async/await
主要是作为可读性功能开发的,因此在视觉上非常简洁自然。 使用旧式的
Promise
语法,您将获得更长的函数。
因此,简而言之,您可以很好地使用observables,而且由于预期的语法差异,它的使用时间更长。

以下是如何将当前代码转换为Rx样式。如果不满足条件,takeWhile将完成您的观察

function doSomething(sID) {
  return from(service.getStudent(sID)).pipe(
    switchMap(student =>
      service.getTeacher(student.TeacherID).pipe(
        takeWhile(teacher => teacher.Active),
        switchMap(teacher => service.teacherSomething(teacher).pipe(takeWhile(res => res))),
        switchMap(() => service.studentSomething(student))
      )
    ))
}

在您的案例中,您可以避免保存教师和学生的值,因为我认为在管道上传播它们在您的用例中是非常正确的

为此,在请求教师后,我将映射响应,并将数据作为元组返回学生和教师

如果老师不活跃,抛出一个错误可能是一个优雅的解决方案,如果你想对错误做些什么,如果你不想做,你也可以返回空的,这是一个不发出并简单完成的可观察结果

因此,这是我的解决方案,考虑到请求“teacherSomething”和“studentSomething”可以并行执行,因为它们似乎并不相互依赖

doSomething(sID){
    service.getStudent(sID).pipe(
        switchMap(studentR =>
          service.getTeacher(student.TeacherID).pipe(map((teacherR) => [studentR, teacherR]))),
        switchMap(([studentR, teacherR]) => {
          if(!teacherR.Active){
              throw new Error('Teacher is not active'); // or return EMPTY
          }
          // I think this two request may have been done in parallel, if so, this is correct.
          return zip(service.teacherSomething(teacher), service.studentSomething(student));
        })
    ).subscribe(
      ([teacherSomethingR, studentSomethingR]) => {/* do something with responses */},
      (error) => { /* Do something if teacher not active, or some request has been error...*/ }
    );
  }
如果请求不能并行执行,我将执行与之前相同的操作(switchMap),并返回响应的元组,以便在需要时执行某些操作。如果不需要,您可以避免最后一步:

doSomething(sID){
  service.getStudent(sID).pipe(
      switchMap(studentR =>
        service.getTeacher(student.TeacherID).pipe(map((teacherR) => [studentR, teacherR]))),
      switchMap(([studentR, teacherR]) => {
        if(!teacherR.Active){
            throw new Error('Teacher is not active'); // or return EMPTY
        }
        // Both request teacher something and student something done in 'serie'
        return service.teacherSomething(teacher)
            .pipe(switchMap((teacherSomethingR) => 
                service.studentSomething(student)
                .pipe(map((studentSomethingR) => [teacherSomethingR, studentSomethingR]))
            ))
      })
  ).subscribe(
    ([teacherSomethingR, studentSomethingR]) => {/* do something with responses */},
    (error) => { /* Do something if teacher not active, or some request has been error...*/ }
  );
}

希望这有帮助

但是如果我需要做一些事情,比如如果teacherSomethingResponse为null,那么做另一个调用呢?这意味着我的链是错误的,因为我不应该输入到达服务的行。teacherSomething只要teacher.Active==false
doSomething(sID){
  service.getStudent(sID).pipe(
      switchMap(studentR =>
        service.getTeacher(student.TeacherID).pipe(map((teacherR) => [studentR, teacherR]))),
      switchMap(([studentR, teacherR]) => {
        if(!teacherR.Active){
            throw new Error('Teacher is not active'); // or return EMPTY
        }
        // Both request teacher something and student something done in 'serie'
        return service.teacherSomething(teacher)
            .pipe(switchMap((teacherSomethingR) => 
                service.studentSomething(student)
                .pipe(map((studentSomethingR) => [teacherSomethingR, studentSomethingR]))
            ))
      })
  ).subscribe(
    ([teacherSomethingR, studentSomethingR]) => {/* do something with responses */},
    (error) => { /* Do something if teacher not active, or some request has been error...*/ }
  );
}