Angular抽象类TypeError

huangapple go评论116阅读模式
英文:

Angular Abstract Class TypeError

问题

以下是您要翻译的内容:

I am getting an odd Type Error when I start using Abstract Classes in Angular 16.

> Error: Uncaught (in promise): TypeError: this.httpService.get is not a function

Maybe my understanding around the useage of Abstract Classes is wrong?
It works when I remove the Abstract class and just call the http.service directly.

Models/HttpResponse.ts

export class HttpResponse {
  status: string | undefined;
  data: any;
  success: string | undefined;
  message: string | undefined;
}

Services/http.abstract_service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})

export abstract class AbstractHttpService {
  public abstract get(url: string): Observable<any>;
}

Services/http.service.ts

import { AbstractHttpService } from './http.abstract_service';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpResponse } from '@models/http_response';

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})

export class HttpService implements AbstractHttpService {

  constructor(private http: HttpClient){ }

  // GET Request
  get(url: string): Observable<any> {
    return this.http.get(url, { observe: 'response' }).pipe(
      map((res: any) => {
        let responseBody = res?.body;
        let result: HttpResponse;
        if(res){
          result = { 
            status: res.status, 
            data: responseBody.data,
            success: responseBody.success, 
            message: responseBody.message
          }
        }
        else {
          console.log(`Error! HttpStatus: ${res.status}`);
        }
        return result;
      }));
  }
}

Services/data.service.ts

import { Injectable } from '@angular/core';
import { AbstractHttpService } from './http.abstract_service';
import { HttpResponse } from '@models/http_response';

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})

export class DataService {
  constructor(private httpService: AbstractHttpService ){ }

  getMyData(): Observable<HttpResponse> {
    const url = `${MyApiUrl}/Data`;

    // This is the problem? When I make it of type HttpService and avoid the abstract class it works.
    const response = this.httpService.get(url);
    return response;
  }
}

Pages/my/my.component.ts

import { Component, OnInit } from '@angular/core';
import { Result } from '@models/result';
import { DataService } from '@services/data.service';
import { HttpResponse } from '@models/http_response';

@Component({
  selector: 'app-my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.scss']
})

export class MyComponent implements OnInit {

  dataSource: Result[] = [];

  constructor(private dataService: DataService) { }

  onGetMyData() {
    this.dataService.getMyData().subscribe((response: HttpResponse) => {
      console.log(`Status: ${response.status} Success: ${response.success} Data:`, response.data.results);

      response.data.results.forEach((val: any) => {
        this.dataSource.push(Object.assign({}, val))
      });
    });
  }

  async ngOnInit() {
    await this.onGetMyData();
  }
}

希望对您有所帮助!

英文:

I am getting an odd Type Error when I start using Abstract Classes in Angular 16.

> Error: Uncaught (in promise): TypeError: this.httpService.get is not a function

Maybe my understanding around the useage of Abstract Classes is wrong?
It works when I remove the Abstract class and just call the http.service directly.

Models/HttpResponse.ts

export class HttpResponse {
  status: string | undefined;
  data: any;
  success: string | undefined;
  message: string | undefined;
}

Services/http.abstract_service.ts

import { Injectable } from &#39;@angular/core&#39;;
import { Observable } from &#39;rxjs&#39;;

@Injectable({
	providedIn: &#39;root&#39;
})

export abstract class AbstractHttpService {
	public abstract get(url: string): Observable&lt;any&gt;;
	
}

Services/http.service.ts

import { AbstractHttpService } from &#39;./http.abstract_service&#39;;
import { HttpClient } from &#39;@angular/common/http&#39;;
import { Injectable } from &#39;@angular/core&#39;;
import { HttpResponse } from &#39;@models/http_response&#39;;

import { Observable } from &#39;rxjs&#39;;
import { map } from &#39;rxjs/operators&#39;;

@Injectable({
	providedIn: &#39;root&#39;
})

export class HttpService implements AbstractHttpService {

	constructor(private http: HttpClient){ }


	// GET Request
	get(url: string): Observable&lt;any&gt; {


		return this.http.get(url, {observe: &#39;response&#39;}).pipe(
			map((res: any) =&gt; {
				let responseBody = res?.body;
				let result: HttpResponse;
				if(res){

					result = { 
						status: res.status, 
						data: responseBody.data,
						success: responseBody.success, 
						message: responseBody.message
					}
				}
				else {
					console.log(`Error! HttpStatus: ${res.status}`);
				}

				return result;
			}));
	}

Services/data.service.ts

import { Injectable } from &#39;@angular/core&#39;;
import { AbstractHttpService } from &#39;./http.abstract_service&#39;;
import { HttpResponse } from &#39;@models/http_response&#39;;

import { Observable } from &#39;rxjs&#39;;
import { map } from &#39;rxjs/operators&#39;;


@Injectable({
	providedIn: &#39;root&#39;
})

export class DataService {
	constructor( private httpService: AbstractHttpService ){ }

	getMyData(): Observable&lt;HttpResponse&gt; {

		const url = `${MyApiUrl}/Data`;

        // This is the problem? When I make it of type HttpService and avoid the abstract class it works.
		const response = this.httpService.get(url);

		return response;
		
	}

Pages/my/my.component.ts

import { Component, OnInit } from &#39;@angular/core&#39;;
import { Result } from &#39;@models/result&#39;;
import { DataService } from &#39;@services/data.service&#39;
import { HttpResponse } from &#39;@models/http_response&#39;;

@Component({
  selector: &#39;app-my&#39;,
  templateUrl: &#39;./my.component.html&#39;,
  styleUrls: [&#39;./my.component.scss&#39;]
})


export class MyComponent implements OnInit {

  dataSource: Result[] = [];

  constructor(private dataService: DataService) { }


   onGetMyData() {
	this.dataService.getMyData().subscribe((response: HttpResponse) =&gt; {

	  console.log(`Status: ${response.status} Success: ${response.success} Data:`, response.data.results);

	  response.data.results.forEach((val: any) =&gt; {
		this.dataSource.push(Object.assign({}, val))
	  });

	});
  }

  async ngOnInit() {
	await this.onGetMyData();
  }


}

Any help appreciated!

答案1

得分: 1

尝试使用 extends 而不是 implement

export class HttpService extends AbstractHttpService
英文:

Try using extends instend of implement

export class HttpService extends AbstractHttpService

答案2

得分: 1

你可能在混淆类:你正在使用抽象类,而不是实现它的类,因此出现了错误。

Services/data.service.ts 中,导入 http 服务类 - Services/http.service.ts,而不是抽象类 - Services/http.abstract_service.ts

尝试这样做:

Services/data.service.ts 中,

而不是:

import { AbstractHttpService } from './http.abstract_service';
    
constructor( private httpService: AbstractHttpService ){ }

使用:

import { HttpService } from './http.service';
    
constructor( private httpService: HttpService ){ }

如果你尝试创建一个具有抽象类不同实现的服务,你可以在 providers 中使用抽象类作为标记,并定义实现它的服务:

providers: [ {provide:AbstractHttpService, useClass: HttpService } ]

例如,以后你可以切换到不同的实现:

providers: [ {provide:AbstractHttpService, useClass: SomeDifferentHttpService } ]
英文:

You're probably mixing classes: you're using abstract class, instead of a class which implements it, hence the error.

In Services/data.service.ts, import the http service class - Services/http.service.ts, not abstract class - Services/http.abstract_service.ts:

Try this:

in Services/data.service.ts,

instead of:

import { AbstractHttpService } from &#39;./http.abstract_service&#39;;

constructor( private httpService: AbstractHttpService ){ }

use

import { HttpService } from &#39;./http.service&#39;;

constructor( private httpService: HttpService ){ }

edit

if you're trying to create a service with different implementations of abstract class, you can use abstract class as a token in providers, and define the service which implements it:

providers: [ {provide:AbstractHttpService, useClass: HttpService } ]

For example, later you can switch to a different implementation:

providers: [ {provide:AbstractHttpService, useClass: SomeDifferentHttpService } ]

huangapple
  • 本文由 发表于 2023年8月10日 21:38:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76876274.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定