将 Http 迁移到 HttpClient

Migrating Http to HttpClient

我正在开展一个项目,该项目需要迁移旧 Http 的所有实例以利用 Angular 提供的新 HttpClient。但是我在迁移其中一种方法时遇到问题。我收到此错误 ERROR TypeError: Cannot read properties of null (reading 'text') at main.js

旧方法:

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;
    });
}

新方法:

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;
        });
}

这就是为什么您不转换为类型 any :) 的原因。如果你删除它,编译器会告诉你 response.text() 不是一个函数,并且将鼠标悬停在响应上会告诉你它已经是一个字符串。您已经将 responseType 作为 text 提供,这就是您返回的结果。

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

此外,您设置 HttpParams 的方式没有任何作用。 set returns 一个值而不是就地修改。你可以这样做:

    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);

无需在订阅回调中使用 async await。请只使用 if (data),对于 nullundefined、空字符串 NaN 和数字 0string "0" 为真)。 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

或者简单地使用三元运算符

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