如何解决这个问题(“ this.http.post(...)。map(...)。concatMap不是函数”)?

时间:2019-01-31 11:16:08

标签: angular

升级角度项目后出现此错误

  

this.http.post(...)。map(...)。concatMap不是函数

enter image description here

这是导致错误的代码

return this.http.post(apiURL, body, options)
        .map(response => response.json())
        .concatMap(response => {
            // Check if the API_TOKEN is expired.
            if (response.error.code == APIErrorCode.API_TOKEN_EXPIRED || response.error.code == 499) {
                // Expired! Check max attempts.
                if (attempts < MAX_REQUEST_ATTEMPT) {
                    console.log("API_TOKEN expired.");
                    return this.requestAPIToken().delay(500)
                            .concatMap(response => this.doPost(api, body, attempts + 1));
                }
                console.log("API_TOKEN expired, request attempt limit reached!");
            }
            return Observable.of(response);
        })
        .catch((err, caught) => {
            // Check if the session authentication token is expired.
            if (authToken && err.status == 403) {
                try {
                    var response = JSON.parse(err._body);
                    if (response.error && response.error.code == APIErrorCode.SESSION_AUTH_TOKEN_EXPIRED) {
                        // Login session expired!
                        return Observable.of(response);
                    }
                } catch (e) { }
            }
            // Check incidental bad request.
            if (err.status == 400 && err.statusText == "Bad Request") {
                try {
                    var response = JSON.parse(err._body);
                    if (response.error && response.error.code == 400 && response.error.message
                            && [ "access denied", "bad" ].includes(response.error.message.toLowerCase())) {
                        // Check max attempts.
                        if (attempts < MAX_REQUEST_ATTEMPT) {
                            return this.requestAPIToken().delay(100)
                                    .concatMap(response => this.doPost(api, body, attempts + 1));
                        }
                        console.log("Bad Request, request attempt limit reached!");
                    }
                } catch (e) { }
            }
            return Observable.throw(err);
        });

在升级我的角度项目之前,它工作正常,我不知道该怎么办

3 个答案:

答案 0 :(得分:4)

如果刚升级了angular,则可能正在使用RxJS v6。如果是这样,则需要重构以使用管道运算符

还请注意,您应该使用HttpClient而不是Http,因为现在已经过时了。然后,您也可以使用response.json()删除第一张地图,因为HttpClient会自动为您完成。

请记住,您需要重构代码中的所有可观察变量,不仅是HttpClient中的可观察变量,还应该重构具有delay运算符的变量。

在这里查看更多信息:

https://rxjs-dev.firebaseapp.com/guide/v6/migration

import { of, throwError } from 'rxjs';
import { concatMap, catchError, delay } from 'rxjs/operators';

return this.httpClient.post(apiURL, body, options)
    .pipe(
        concatMap(response => {
            // Check if the API_TOKEN is expired.
            if (response.error.code == APIErrorCode.API_TOKEN_EXPIRED || response.error.code == 499) {
                // Expired! Check max attempts.
                if (attempts < MAX_REQUEST_ATTEMPT) {
                    console.log("API_TOKEN expired.");
                    return this.requestAPIToken().pipe(
                        delay(500),
                        concatMap(response => this.doPost(api, body, attempts + 1)
                    );
                }
                console.log("API_TOKEN expired, request attempt limit reached!");
            }
            return of(response);
        }),
        catchError((err, caught) => {
            // Check if the session authentication token is expired.
            if (authToken && err.status == 403) {
                try {
                    var response = JSON.parse(err._body);
                    if (response.error && response.error.code == APIErrorCode.SESSION_AUTH_TOKEN_EXPIRED) {
                        // Login session expired!
                        return of(response);
                    }
                } catch (e) { }
            }
            // Check incidental bad request.
            if (err.status == 400 && err.statusText == "Bad Request") {
                try {
                    var response = JSON.parse(err._body);
                    if (response.error && response.error.code == 400 && response.error.message
                        && [ "access denied", "bad" ].includes(response.error.message.toLowerCase())) {
                        // Check max attempts.
                        if (attempts < MAX_REQUEST_ATTEMPT) {
                            return this.requestAPIToken().pipe(
                                delay(100),
                                concatMap(response => this.doPost(api, body, attempts + 1)
                            );
                        }
                        console.log("Bad Request, request attempt limit reached!");
                    }
                } catch (e) { }
            }
            return throwError(err);
        })
    );

如果您使用的是v5.5,那么我的回答也应该有所帮助,但是您的问题是准确地缺少了concatMap运算符导入。重构为可管道运算符,或仅添加import 'rxjs/add/operator/concatMap';

此导入将使用Observable运算符猴子修补concatMap对象-默认情况下不存在。

有关在RxJS v5中导入运算符的更多信息:

https://www.learnrxjs.io/concepts/operator-imports.html

答案 1 :(得分:1)

扩展@MartinAdámek的答案:- 应该是这样的

return this.http.post(apiURL, body, options).pipe(
     map(response => response.json()),
     concatMap(response => {
        //REST OF THE CODE
        return of(response);
    }))

此外,您无需编写 Observable.of(响应),现在您只需编写 of(响应) 这也适用于 Observable.throw()

答案 2 :(得分:0)

您可能正在使用RxJS。如果要合并map, filter, reduce等...,请使用.pipe()

return this.http.post(...).pipe(
 map(...).reduce(...)
}))

这样,您可以组合多种方法。