【问题标题】:Typescript magic: http client get does not fire the request打字稿魔术:http客户端获取不会触发请求
【发布时间】:2018-12-29 03:10:07
【问题描述】:

我需要帮助 :) 我正在开始创建授权服务,突然 http 客户端无法在此服务中工作,我不知道为什么,在玩了四个小时的代码后也没有任何想法。服务真的很简单。

import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import { UrlsService, Urls } from '@app/shared/urls';
import { Injectable } from '@angular/core'

@Injectable()
export class AuthorizationService {
    private _permissions: string[];

    constructor(
        private httpClient: HttpClient,
        private urlsService: UrlsService) {

    }

    refreshPermissions(): Observable<string[]> {
        return this.httpClient
            .get('http://localhost:54531/api/account/permissions', { observe: 'response'})
            .map(response => {
                console.log(response);
                return this._permissions;
            });
    }

    get permissions(): string[] {
        return this._permissions;
    }

refreshPermissions 方法调用每个用户的凭据更新。看看 app.component.ts

ngOnInit() {  
       this.authenticationService.setCredentialsSubject.subscribe(() => this.authorizationService.refreshPermissions());
       this.authenticationService.loadCredentialsFromLocalStorage();
}

我已经在 map 函数上设置了断点来查看响应结构。但相反,我看到了错误。此外,在网络选项卡中,我可以看到该请求尚未触发。最后,map labmda 中的断点从未触发过。

我花了四个小时试图找出错误,但没有成功。你知道会发生什么吗?

附言。第一个屏幕的错误

"SyntaxError: Unexpected end of input
    at AuthorizationService.refreshPermissions (webpack-internal:///./src/app/core/authentication/authorization/authorization.service.ts:14:14)
    at SafeSubscriber.eval [as _next] (webpack-internal:///./src/app/app.component.ts:40:116)
    at SafeSubscriber.__tryOrUnsub (webpack-internal:///./node_modules/rxjs/_esm5/Subscriber.js:245:16)
    at SafeSubscriber.next (webpack-internal:///./node_modules/rxjs/_esm5/Subscriber.js:192:22)
    at Subscriber._next (webpack-internal:///./node_modules/rxjs/_esm5/Subscriber.js:133:26)
    at Subscriber.next (webpack-internal:///./node_modules/rxjs/_esm5/Subscriber.js:97:18)
    at Subject.next (webpack-internal:///./node_modules/rxjs/_esm5/Subject.js:66:25)
    at AuthenticationService.setCredentials (webpack-internal:///./src/app/core/authentication/authentication.service.ts:86:37)
    at AuthenticationService.loadCredentialsFromLocalStorage (webpack-internal:///./src/app/core/authentication/authentication.service.ts:61:14)
    at AppComponent.ngOnInit (webpack-internal:///./src/app/app.component.ts:41:36)"

【问题讨论】:

  • 我不知道你的httpClient 是什么,但奇怪的是get() 后面紧跟着map()。不应该有await,promise什么的吗?
  • 你也需要订阅 refreshPermissions:this.authenticationService.setCredentialsSubject.subscribe(() => this.authorizationService.refreshPermissions().subscribe(result => {}));
  • @DanielKhoroshko 我在代码示例中添加了导入部分,httpClient 来自@angular/common/httphttpClient.get 返回且可观察。
  • @A.Winnen 谢谢,现在我明白了,如果没有订阅者 - observable 不会触发。
  • @A.Winnen 您可以发布答案,否则我稍后再做。

标签: angular typescript rxjs httpclient angular6


【解决方案1】:

您没有订阅 refreshPermissions 功能。如果没有订阅,您的函数将不会被触发。

你可以通过使用这个 ngOnInit 函数来简单地解决这个问题:

ngOnInit() {  
   this.authenticationService.setCredentialsSubject.subscribe(() => this.authorizationService.refreshPermissions().subscribe(result => {}));
   this.authenticationService.loadCredentialsFromLocalStorage();
}

比拥有多个订阅更好的是使用 rxjs 的运算符之一,例如 flatmap:

ngOnInit() {  
    this.authenticationService.setCredentialsSubject.flatMap(() => 
        this.authorizationService.refreshPermissions()
    ).subscribe(result => {
        //do something with result of refreshPermissions observable
    });
    this.authenticationService.loadCredentialsFromLocalStorage();
}

最终代码

permissions.service

import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import { UrlsService, Urls } from '@app/shared/urls';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

type PermissionType = 'Permission1' | 'Permission2';
type PermissionsSubject = BehaviorSubject<PermissionType[]>;

export class AuthorizationService {
    private _permissionsSubject: PermissionsSubject = new BehaviorSubject<PermissionType[]>([]);

    constructor(
        private httpClient: HttpClient,
        private urlsService: UrlsService) {

    }

    refreshPermissions(): void {
        const getPermissionsObservable = this.httpClient
            .get<PermissionType[]>(this.urlsService.getUrl(Urls.GET_PERMISSIONS));
        getPermissionsObservable.subscribe(permissions => this._permissionsSubject.next(permissions));
    }

    get permissions(): PermissionType[] {
        return this._permissionsSubject.value;
    }

    get permissionsSubject(): PermissionsSubject {
        return this._permissionsSubject;
    }
}

在 app.component 中

ngOnInit() {
    authenticationService.setCredentialsSubject.subscribe(() => authorizationService.refreshPermissions());
    authenticationService.loadCredentialsFromLocalStorage()
}

【讨论】:

  • 因为它可预测且易于使用。 F.e.编辑服务应该刷新用户操作的权限,而不是使用权限。一行代码:this.permissionsService.refreshPermissions().then(permissions =&gt; { })。但是如果只使用行为主题 - 你应该订阅它并在代码的其他部分调用 refreshPermissions。
  • 已删除 cmets :) 问题是为什么返回类型不是 void :)
  • 但是如果你订阅了 refreshPermissions,你会调用 API 两次。
  • 没关系,我想返回行为主题,但在这种情况下,您将只有一个事件流 - permissionsSubject。通过返回 observable,我可以在从服务器加载权限时单独订阅事件,以及从任何来源设置的权限,此外,将来我可以添加更多方法 refreshPermissionsByServer2 并且每个方法都将返回 observable 我可以分离事件流。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-16
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多