Home > Net >  Migrating Http to HttpClient
Migrating Http to HttpClient

Time:03-18

I am working on a project which will need to migrate all instances of the old Http to utilize the new HttpClient provided by Angular. But I am having issues with the migration of one of my methods. I get this error ERROR TypeError: Cannot read properties of null (reading 'text') at main.js

Old Method:

ngAfterViewInit(): void {

    var header = this.header;
    if (header == null)
        return;

    var params = new URLSearchParams();

    params.set('manufacturerCode', `${header.manufacturerCode || 0}`);
    params.set('typeCode', `${header.typeCode || 0}`);
    params.set('typeRevisionCode', `${header.typeRevisionCode || 0}`);
    params.set('protocol', `${header.protocol || 0}`);
    params.set('serialNumber', header.serialNumber);
    params.set('tag', header.tag);

    this.http.get(`./api/devices/device-icon`, { search: params }).pipe(map((response: Response) => response.text())).subscribe(data => {

        let source: string;

        if (data != null && data.length > 0)
            source = `data:image/x-icon;base64,${data}`;
        else
            source = './assets/Default_Device_Icon.ico'; // use the default device icon

        this.renderer.setElementAttribute(this.elementRef.nativeElement, 'src', source);
        this.invisible = false;
    });
}

New Method:

ngAfterViewInit(): void {

    var header = this.header;
    if (header == null)
        return;

    var params = new HttpParams();

    params.set('manufacturerCode', `${header.manufacturerCode || 0}`);
    params.set('typeCode', `${header.typeCode || 0}`);
    params.set('typeRevisionCode', `${header.typeRevisionCode || 0}`);
    params.set('protocol', `${header.protocol || 0}`);
    params.set('serialNumber', header.serialNumber);
    params.set('tag', header.tag);

    this.httpClient.get(`./api/devices/device-icon`, { params, responseType: 'text'})
        .pipe(map((response: any) => response.text()))
        .pipe(takeUntil(this.ngUnsubscribe))
        .subscribe(async data => {
            let source: string;

            if (data != null && (await data).length > 0)
                source = `data:image/x-icon;base64,${data}`;
            else
                source = './assets/Default_Device_Icon.ico'; // use the default device icon

            this.renderer.setAttribute(this.elementRef.nativeElement, 'src', source);
            this.invisible = false;
        });
}

CodePudding user response:

This is why you don't cast to type any : ) . If you remove that, the compiler will tell you that response.text() is not a function, and hovering over the response tells you it is already a string. You've already supplied the responseType as text so that is what you get back.

this.httpClient.get(`./api/devices/device-icon`, { params, responseType: 'text'})
        // Removed the map call
        .pipe(takeUntil(this.ngUnsubscribe))

Also, the way you set HttpParams is doing nothing. set returns a value rather than modifying in place. You can do it like this:

    const params = new HttpParams()
      .set('manufacturerCode', `${header.manufacturerCode || 0}`)
      .set('typeCode', `${header.typeCode || 0}`)
      .set('typeRevisionCode', `${header.typeRevisionCode || 0}`)
      .set('protocol', `${header.protocol || 0}`)
      .set('serialNumber', header.serialNumber)
      .set('tag', header.tag);

No need to use async await inside a subscribe callback. And please just use if (data), this will be false for null, undefined, empty string, NaN, and the number 0 (the string "0" is true). https://developer.mozilla.org/en-US/docs/Glossary/Truthy

.subscribe((data) => {
        let source: string;
        if (data) source = `data:image/x-icon;base64,${data}`;
        else source = './assets/Default_Device_Icon.ico'; // use the default device icon

or simply use the ternary operator

        const source = data
          ? `data:image/x-icon;base64,${data}`
          : './assets/Default_Device_Icon.ico'; // use the default device icon
  • Related