【问题标题】:Angular Asynchronous function with HttpClient带有 HttpClient 的 Angular 异步函数
【发布时间】:2021-10-29 21:10:05
【问题描述】:

好的,所以我整天都在为这个问题摸不着头脑。本质上,我有一个按钮可以让学生退学。那部分很简单。但是,它还应该检查数据库中该班级的等候名单,如果有的话,请登记下一个排队的人。

所以在我看来,操作的顺序是……

  1. 存储课程 ID 以供将来使用
  2. 让学生 A 退出课堂 (HTTP #1)
  3. 获取该课程的等候名单(这是我使用保存的 ID 的地方)(HTTP #2)
  4. 制作一个响应数组
  5. 如果数组长度为0,则结束
  6. 如果数组长度大于0,继续
  7. 从数组 [0] 创建一个学生 B 对象
  8. 让学生 B 加入课程 (HTTP #3)
  9. 从等候名单中删除学生 B。 (HTTP #4)

我可以很好地编写代码以进行编译,并且每个单独的部分都可以正常工作。但是在一起,我的同步函数变得异步并且不能按预期工作。罪魁祸首是第 3 步和第 4 步。虽然第 3 步仍处于等待状态,但 JS 移动到第 4 步并且代码停止,因为显然数组是空的。

onWithdrawClass(row:any){
    let courseId = row.courseId;

    //display a confirmation message
    if(confirm("Are you sure you want to withdraw from this course?\n \nYou may not be able to get your seat back if you do.")){
      
      //use the api service to perform the withdraw and refresh the list
      this.api.deleteWithdraw(row.id).subscribe(res=>{
        alert("You have been successfully withdrawn from this course.");
          let ref = document.getElementById('refresh');
          ref?.click();
      },
      err=>{
        alert("Something went wrong with withdrawal.\nTry refreshing the page to see if it worked.");
      })

      //get waiting list for that course
      this.api.getWaitlistByCourseId(courseId).subscribe(res=>{
        this.courseById = res;
      })

      //do this if there is someone waiting for that class
      if(this.courseById.length > 0){
        //create student object
        this.studentObj.id = this.courseById[0].id;
        this.studentObj.courseId = this.courseById[0].courseId;
        this.studentObj.courseName = this.courseById[0].courseName;
        this.studentObj.courseInstructor = this.courseById[0].courseInstructor;
        this.studentObj.studentFirstName = this.courseById[0].studentFirstName;
        this.studentObj.studentLastName = this.courseById[0].studentLastName;
        this.studentObj.studentEmail = this.courseById[0].studentEmail;
        
        //enroll that student from wait list into course
        this.api.enrollStudent(this.studentObj).subscribe(res=>{
          console.log("waiting list student enrolled.")
        },
        err=>{
          console.log("error with enrolling waiting list student.")
        })
        //remove that student from wait list
        this.api.deleteFromWaitingList(this.courseById[0].id).subscribe(res=>{
          console.log("student removed from waiting list")
        },
        err=>{
          console.log("error with deleting student from waiting list")
        })
      }
    }
  }

和 api 服务 ts

enrollStudent(data:any){
        return this.httpClient.post<any>("ENROLL-URL", data)
        .pipe(map((res:any)=>{
          return res;
        }))
      }

deleteWithdraw(id:number){
        return this.httpClient.put<any>("WITHDRAW-URL", id)
        .pipe(map((res:any)=>{
          return res;
        }))
      }

getWaitlistByCourseId(courseId:string){
        return this.httpClient.post<any>("WAITLIST-URL", courseId)
        .pipe(map((res:any)=>{
          return res;
        }))
      }

deleteFromWaitingList(id:number){
        return this.httpClient.put<any>("WAITLIST-DELETE-URL", id)
        .pipe(map((res:any)=>{
          return res;
        }))
      }

我认为使用 async/await 将是“正确”执行此操作的最佳方法,但我不知道如何从 http 调用中获得承诺或等待它。

(ps。如果你正在查看我的 httpClient 调用并说“你有 .put 用于删除和 .post 用于获取”我知道。这很奇怪。这只是让它工作的唯一方法Cosmos DB。它们都有效,我保证,这不是问题。)

已解决:

感谢 munleashed 的帮助!在我的情况下,他的回答并没有完全解决这个问题,但这就是让我头脑发热的原因。对于在这里寻找解决方案的任何人,这就是我的结尾......

courseById: any[] = [];

async doTheThingZhuLi(courseId: undefined){
    this.response = await this.http.post<any>("WAITLIST-URL", courseId)
    .pipe(map((res:any)=>{
      this.courseById = res;
    })).toPromise();
  }

onClickWithdraw(row:any){
    if(confirm("Are you sure you want to withdraw from this course?")){
      this.doTheThingZhuLi(row.courseId).then(res=>{
        this.moveFromWaitList(); //this handles steps 6 - 9
      }
      ).finally(() =>{
        this.actuallyWithdrawTheStudent(row.id);
      });
    }
  }

【问题讨论】:

    标签: javascript angular typescript async-await httpclient


    【解决方案1】:

    我不确定我是否完全理解您想要做什么,但我发现您在 api 调用的同步方面遇到了问题。 如果您想等待一个 API 调用完成以便调用另一个 API 调用,则必须使用一些 RXJS 可管道运算符。 比如:

    const api1 = this.service.getApi1();
    const api2 = this.service.getApi2();
    
    api1.pipe(switchMap(api1Result => {
    // Here you can use result of api1 call
    
    return ap2;
    }).subscribe(api2Result => {
    // Here you can use result of api2Call
    });
    

    基本上,机制与 Promises 的工作方式类似:

    console.log(1);
    const promise = new Promise((res) => {res()});
    promise.then(res => console.log('3'));
    console.log(4);
    
    // It will print 1 4 3 (3 at the end because its an asyns operation)
    

    Observables 和 RXJS 的逻辑是一样的。这就是为什么您无法将代码与您的方法同步的原因。看看我的第一个例子,然后从它开始。

    【讨论】:

    • 感谢您的帮助,@munleashed!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    相关资源
    最近更新 更多