【问题标题】:How to wait for subscribe to finish with pipe and map如何等待订阅完成管道和地图
【发布时间】:2020-12-25 20:11:47
【问题描述】:

在我的后端 - express.js 中,我成功返回了一个布尔值,它告诉我用户是否存在。

问题出在我的前端 - angular(最新版本),当我收到该值时,我需要在异步执行后立即使用该值。

所以我决定使用 RxJS 管道 + 地图

我明白了:

Argument of type 'Observable<unknown>' is not assignable to parameter of type 'OperatorFunction<boolean, unknown>'.
  Type 'Observable<unknown>' provides no match for the signature '(source: Observable<boolean>): Observable<unknown>'.ts(2345)
The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<unknown>'.

ApiService.ts

checkIfUserExists(email: string): Observable<boolean> {
    return this.http.get<boolean>(`${this.COINS_URL}/login/check/${email}`);
  }

register.component.ts

let value = null
        this.apiService.checkIfUserExists(this.user.email)
  .pipe(
    map(data => console.log(data))
  )
    console.log(value) -- returns [object Object]

如何解决这个问题并成功使用管道+地图?

为 cmets 编辑:

checkIfUserExists() {
    this.user = this.userRegistrationForm.value
    return this.apiService.checkIfUserExists(this.user.email)
      .pipe(
        map(data => data))
      .subscribe(e => e.userExists)
  }

尝试使用时 - 我得到 [object Object]

userExists = this.checkIfUserExists()
    console.log('userExists: ' + userExists)

编辑 2:最终解决方案,感谢所有帮助 使用回调解决了问题 非常感谢这篇文章:How do I return the response from an asynchronous call?

代码:

checkIfUserExists(callback) {
    this.user = this.userRegistrationForm.value
    console.log("2. callback here is the function passed as argument above...")
    this.apiService.checkIfUserExists(this.user.email)
      .pipe(
        map(data => data))
      .subscribe(e => {
        console.log("3. start async operation...")
        console.log("4. finished async operation, calling the callback, passing the result...")
        callback(e.userExists)
      })
  }

onSubmit() {
    let userExists = null
    console.log("1. function called...")
    this.checkIfUserExists((result: boolean) => {
      // 5. Received the result from the async function,
      //    now do whatever you want with it:
      console.log("5. result is: ", result);
      userExists = result
      this.userExistsValidator(userExists)
  });
  }

【问题讨论】:

  • 您也可以选择接受以下任何一个答案 1. 在这种情况下无需订阅两次 2. 如果您对userExists 属性感兴趣,那么您可以项目从地图运营商即.map(data =&gt; data.userExists)和订阅块中,您可以直接访问布尔值,如.subscribe(e =&gt; console.log(e));

标签: angular rxjs observable angular2-observables


【解决方案1】:

您需要从 .pipe(map) 返回,如下所示。这将导致函数等待服务获取响应然后返回值。因此,在服务得到任何响应之前,这样做不会返回 null 值或从函数返回。

let value = null
        return this.apiService.checkIfUserExists(this.user.email)
  .pipe(
    map(data =>{
    console.log(data);    
    return data; 
    })
  );

【讨论】:

  • 这是很有价值的评论。我确实有问题,如果我将 apiService return 放在一个单独的方法中,该方法将是 Observable 类型,如果我这样称呼它: let userExists = null this.checkIfUserExists() .subscribe(res => { console .log('res: ' + res) userExists = res }) console.log('userExists: ' + userExists) - 仍然返回 null 但我必须再次订阅才能访问方法内的代码。由于 Observable 而订阅是必要的,还是它?
【解决方案2】:

查看文档中map 的签名。您将需要返回一个 observable。签名:

map(project: Function, thisArg: any): Observable

现在进行以下更改:

checkIfUserExists() { 
   return this.apiService.checkIfUserExists(this.user.email)
    .pipe(
      map(data => data)  // needed only if you need projection
      })
    );
}

注意事项:

  1. map 运算符中只有一条语句时,省略 {}return
  2. 在这种情况下,我认为您不需要 map 运算符,除非您尝试从 observable 中投影某些属性。
  3. 除非您订阅一个可观察对象,否则它不会从中发出值。

使用:(因为它是异步的)调用它

this.checkIfUserExists().subscribe(e => userExists = e);

【讨论】:

  • 感谢您的评论,请看一下我的编辑,我想不通
  • 根据您的最新评论编辑了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 2019-09-23
  • 2019-07-13
  • 1970-01-01
相关资源
最近更新 更多