javascript - 订阅放置在 Promise Angular 6 中的 http.post

标签 javascript angular rxjs firebase-authentication observable

当我将 promise 与 subscribe 和另一个异步任务混合在一起时,这对我来说变得很复杂。

这是我的身份验证服务:

getCurrentUserToken(){
    return new Promise((resolve,reject)=>{
      firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
        resolve(idToken)
      }).catch(function(error) {
        reject(error)
      });
    }) 
  }

这是我的 HTTP 服务:
sendEmail(email) {

    return this.authService.getCurrentUserToken().then(token => {
      const httpOptions = {
        headers: new HttpHeaders({
          'Content-Type': 'application/json',
          'Authorization': 'Basic server-Password',
        })
      };
      let data = email
      data['idToken'] = token
      return this.http.post(this.apiServer + 'sendEmail', data, httpOptions)
    })

  }

这就是我如何称呼 sendEmail(email)组件中的函数:
    Observable.fromPromise(this.httpService.sendEmail(element)).subscribe(
      data3 => {
        console.log(data3)

      }, error => {
        console.log(error)
      }
    ))

我必须将 currentUserToken 传递给 API 以让 API 对用户 session 进行身份验证。尽管如此,getCurrentUserToken() sendEmail()正在异步运行,所以我必须使用 Promise通过TokensendEmail()函数,并让 sendEmail 函数调用 API 发送电子邮件。

没有 promise ,我可以订阅 http.post像这样:
this.httpService.sendEmail(element).subscribe(
          data3 => {
            console.log(data3)

          }, error => {
            console.log(error)
          }
        ))

不幸的是,当我将 promise 添加到其中时,我搞砸了,console.log 正在返回:Observable {_isScalar: false, source: Observable, operator: MapOperator}
请告知如何订阅 http.post位于 Promise 内.

最佳答案

这里真的没有必要让事情复杂化。

我将使用 async/await语法在这里和为此,我们将不得不使用 Promise s 而不是 Observable s。好消息是,我们可以利用 toPromise() Observable 上的方法值将其更改为 Promise
也关注我在代码中的注释

这是实现

对于 getCurrentUserToken

getCurrentUserToken() {
  return firebase.auth().currentUser.getIdToken(true);
  // This will already return a Promise<string>
  // So no need to do a .then and then return from there.
}

对于 sendEmail
async sendEmail(email) {
  // Since getCurrentUserToken returns a Promise<string> we can await it
  const token = await this.authService.getCurrentUserToken();
  // token will now have the Current User Token
  const httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
      'Authorization': 'Basic server-Password',
    })
  };
  let data = email
  data['idToken'] = token
  return this.http.post(this.apiServer + 'sendEmail', data, httpOptions).toPromise();
  // Notice how we're calling the .toPromise() method here 
  // to change Observable into a Promise
}

如何使用它?

此代码将进入您之前调用 this.httpService.sendEmail 的组件方法中. 请务必将该功能标记为 async尽管。
// We can only await something in a function which is declared of type async
async sendEmail() {
  try {
    const data = await this.httpService.sendEmail(element);
    // Since sendEmail again returns a Promise, I can await it.
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

关于javascript - 订阅放置在 Promise Angular 6 中的 http.post,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52794858/

相关文章:

angular - Primeeng 菜单栏 ng-template 开始和结束或即使在示例中以相同的方式执行后也不显示

typescript - 订阅中的变量更改后,Angular 2 View 不会更新

javascript - RxJS:每隔x秒进行一次

javascript - Progressbar.js - 如何获得第二个圆圈?

angular - 如何在 rxjs retryWhen 方法中使用 Angular 服务

javascript - 如何从 Controller 调用指令?

javascript - 使用 Angular 6 中的 Observable 捕获 Promise 拒绝错误

node.js - 如何将 RxJs observable 的结果作为 Node.js 的剩余响应返回

javascript - react 警告 : flattenChildren(. ..) : Encountered two children with the same key, `.${index}`

javascript - 完全从 html 中解耦 Angular