在 TypeScript 中包装 Firebase 承诺

Posted

技术标签:

【中文标题】在 TypeScript 中包装 Firebase 承诺【英文标题】:Wrapping a Firebase promise in TypeScript 【发布时间】:2020-03-27 07:48:19 【问题描述】:

我正在尝试将两个函数转换为更多的 DRY 代码:

  async registerUser(newUser: User) 
    await this.db.auth
      .createUserWithEmailAndPassword(newUser.email, newUser.pass)
      .then(data => 
        this.db.auth.currentUser.getIdToken().then(reply => 
          this.http
            .post('http://localhost:3000/login',  token: reply )
            .toPromise()
            .then(response => 
              if (response['valid'] === 'true') 
                localStorage.setItem('user', JSON.stringify(reply));
                this.router.navigate(['dash']);
              
            );
        );
      )
      .catch(err => 
        console.log('registration failed: ' + err.message);
      );
  

  async signIn(newUser: User) 
    await this.db.auth
      .signInWithEmailAndPassword(newUser.email, newUser.pass)
      .then(data => 
        this.db.auth.currentUser.getIdToken().then(reply => 
          this.http
            .post('http://localhost:3000/login',  token: reply )
            .toPromise()
            .then(response => 
              if (response['valid'] === 'true') 
                localStorage.setItem('user', JSON.stringify(reply));
                this.router.navigate(['dash']);
              
            );
        );
      )
      .catch(err => 
        console.log('signIn failed: ' + err.message);
      );
  

我想创建一个单独的方法来包装这两种方法,这样我就可以重复使用相同的代码。我正在写一个方法,这就是我到目前为止所拥有的,这就是我需要问这个问题的地方。我不确定如何最好地结合这些方法,因为我不熟悉 Promise。我应该在这两个承诺的 resolve() 部分返回什么来使我的新方法正常工作?

  async useAuth(user: User, action: string) 
    if (action === 'signIn') 
      return await new Promise((resolve, reject) => 
        this.db.auth.signInWithEmailAndPassword(user.email, user.pass);
      );
     else if (action === 'register') 
      return await new Promise((resolve, reject) => 
        this.db.auth.createUserWithEmailAndPassword(user.email, user.pass);
      );
    

【问题讨论】:

这两个登录和创建方法不是已经返回承诺了吗?您可以在不包装的情况下退回它们。 firebase.google.com/docs/reference/js/firebase.auth.Auth 但我的目标是在前两种方法中重复使用相同的代码。我可以修改登录的最终结果并创建方法来适应这一新变化 前两个也是一样的,你可以返回全部的东西,因为它们也是承诺 Promise.resolve().then().catch() 也是一个promise 【参考方案1】:

这两个函数都已返回 Promise<UserCredential>。因此,无需将它们包装在另一个 Promise 中。

async useAuth(user: User, action: string) 

    let result; // type is UserCredential

    if (action === 'signIn') 
    
      result = await this.db.auth.signInWithEmailAndPassword(user.email, user.pass);
     
    else if (action === 'register') 
    
      result = await this.db.auth.createUserWithEmailAndPassword(user.email, user.pass);
    
    else
    
        throw "unknown action " + action;
    

    return result;

【讨论】:

【参考方案2】:

NineBerry 的回答是正确的,我最终实现了:

  async useAuth(user: User, action: string) 
    if (action === 'signIn')
      return await this.db.auth.signInWithEmailAndPassword(user.email, user.pass);
    else if (action === 'register')
      return await this.db.auth.createUserWithEmailAndPassword(user.email, user.pass);
  

我是这样做的!

【讨论】:

当你完成代码的重写后,根本不应该有任何.then.catch。混合使用async/await 和对 Promises 的显式处理会使代码更难阅读和理解。由于您已经在使用 async/await,因此您应该在任何地方使用它。

以上是关于在 TypeScript 中包装 Firebase 承诺的主要内容,如果未能解决你的问题,请参考以下文章

找不到模块“firebase”或其相应的类型声明。 React + TypeScript + Firebase

为啥在 Typescript(Firebase 函数)中双重导入 NPM 包

Typescript 中的 React + Firebase 云功能无法部署

在 React 应用程序中为 Firebase 正确的 Typescript 类型

Firebase + Typescript,无法从用户对象中获取 accessToken?

在 TypeScript 中为 Firebase Cloud Function 配置 mailgun