打字稿,承诺和倍数响应类型

时间:2017-10-18 18:13:10

标签: angular typescript es6-promise

尝试学习一些Angular 4,并解决了这个问题。

我有一个REST服务器(Spring Boot),它有一个登陆用户的端点,如果登录成功,将在标头中使用JWT令牌进行响应,否则,使用401或500响应(如果有的话)出错了。)

因此,为了检查登录,我使用了以下代码(在服务中):

export const TOKEN_NAME = 'jwt_token';
const AUTH_HEADER_KEY = 'Authorization';
const AUTH_PREFIX = 'Bearer';

@Injectable()
export class AuthService {

  private headers = new HttpHeaders({ 'Content-Type': 'application/json' });

  constructor(private http: HttpClient) { }

  login(username: string, password: string): Promise<boolean> | Promise<never> 
  {
    const credentials = {
      username: username,
      password: password
    };

    const req = this.http.post(`http://localhost:8080/login`, credentials, { headers: this.headers, observe: 'response' });
    return req.toPromise()
      .then(r => this.processLoginResponse(r))
      .catch(e => this.handleLoginError(e));
  }

  private processLoginResponse(res: HttpResponseBase): boolean {
    if (res.header.has(AUTH_HEADER_KEY)) {
      const authorizationHeaderValue = res.headers.get(AUTH_HEADER_KEY);

      const regex = new RegExp(`^${AUTH_PREFIX} (.*)`);
      const m = regex.exec(authorizationHeaderValue);

      if (m !== undefined && m.length === 2) {
        // TODO: store the token on localstorage
        return true
      }
    }

    return false;
  }

  private handleLoginError(error: HttpErrorResponse): boolean | Promise<never> {
    if (error.status === 401) {
      return false;

    } else if (error.status === 403) {
      // bad request
      return Promise.reject(new Error('Bad request custom message'));

    } else {
      return Promise.reject(new Error('Something goes wrong!'));
    }
  }
}

因此,在我的AuthService中,login方法可以返回布尔值(promise)或错误。

然后,在我的组件中,如果我尝试使用以下代码:

const loginResult = this.authService.login('john_smith', 'secret123').then(r => { console.log(r); });

我收到了错误消息,其中包含以下内容:

TS2349:Cannot invoke an expression whose type lacks a call signature. Type '(<TResult1 = boolean, TResult2 = never>(onfulfilled?: (value: boolean) => TResult1 | PromiseLike<...' has no compatible call signatures.

没有想法如何纠正这一点。

2 个答案:

答案 0 :(得分:1)

Promise<boolean>是一个承诺,在解析后,使用boolean参数调用其回调。

Promise<never>是一个承诺,在解析后,使用never参数调用其回调。但是没有never值,因此永远无法解析Promise<never>

好的,您宣布login()返回Promise<boolean> | Promise<never>。这意味着它返回 一个Promise<boolean>Promise<never>。现在,如果您将其中一个交给我,当我在其上调用then()时,我可以将哪种类型的参数传递给它?好吧,如果它是Promise<boolean>,我可以递给你boolean。但如果它是Promise<never>,我只能递给你never。但我不知道它是哪一个,因为你递给我的东西可以 其中。因此,我唯一可以安全做的就是通过一些 booleannever的内容。所以这只是never。哎呀,这不是你想要的。

您遇到的具体错误是因为TypeScript won't allow you to call a method on a union of types where the method signatures differ。但即使你解决了这个错误,唯一可以安全传递给then()的是never类型。这可能不是你想要的。

让我们回来。

您希望login()返回Promise<boolean> a Promise<never>吗?或者您希望它返回Promise<boolean | never>?这意味着,一个承诺,当解决时,使用 booleannever来调用其回调。换句话说,一个使用boolean调用其回调或从不调用其回调的承诺。换句话说,Promise<boolean>。如果您将login()的返回类型更改为Promise<boolean>,则承诺(如果已解决)将收到boolean。这允许您在其上调用then()

const loginResult = this.authService.login('john_smith', 'secret123').then(r => { console.log(r); }); // okay

这样更好吗?希望有所帮助;祝你好运!

答案 1 :(得分:0)

Promise<never> - 我认为这是造成它的原因。 “never”是一种特殊的TypeScript类型,用于标记永远不会返回的方法 - 例如,它会抛出异常或关闭整个“机器” - nodejs运行时。如果您想标记不返回值的方法,则需要执行Promise<void>