簡體   English   中英

switchMap類型void不能分配給ObservableInput <{}>類型

[英]switchMap Type void is not assignable to type ObservableInput<{}>

我使用Angular http和RXJS來檢索一些應用程序設置。 http使用RXJS shareReplay來避免多個相同的調用。

這是按預期工作,並檢查網絡選項卡我只能看到我的后端API調用。

我的應用程序中的一些組件將調用該服務並使用結果來呈現頁面。 其他組件,需要像上面那樣調用服務,但然后再次對結果做'某事',例如更多的http調用,然后渲染頁面。 當試圖做以后,我得到類型錯誤:

Argument of type '(result: any) => void' is not assignable to parameter of type '(value: any, index: number)' => ObservableInput<{}>

在我的switchMap上使用。

- 沒有switchMap的簡單例子----

cart.component.ts

ngOnInit() {
    this.systemPreferences.getPreferences()
        .subscribe(
            (result: any) => {
                this.headerTitle = result.title || '';
            },
            (err) => {
                console.log('there has been an error');
            },
            () => // Some completion code
        );
}

systemPreferences.service.ts:

const CACHE_SIZE = 1;

export class SystemPreferences {
    private $cache: Observable<Object>

    private requestConfig() {
         return this.http.get("/api/some/endpoint").pipe(
             map(response => response.value)
         );
    }

    public getPreferences() {
        if (!this.cache$) {
            this.cache$ = this.requestConfig().pipe(
             shareReplay(CACHE_SIZE)
            );
        }

        return this.cache$;
    }
}

/ api / some / endpoint示例響應:

{
    "appName": "Tables Forks and Spoons",
    "title": "My title",
    "regionUrls": [
        "http://www.region1.com:8021",
        "http://www.region2.com:8021",
        "http://www.region3.com:8021",
        "http://www.region4.com:8021"
    ],
    "nonRegionUrls": [
        "http://www.non-region1.com:8021",
        "http://www.non-region2.com:8021",
        "http://www.non-region3.com:8021",
        "http://www.non-region4.com:8021"
    ]
}

- 鍵入錯誤簡單示例wit switchMap ----

cart.component.ts

ngOnInit() {
    this.systemPreferences.getPreferences()
        .pipe(
            .switchMap((result: any) => {

               this.systemPreferences.getLiveUrl(result['regionUrls']);

            }))
        .subscribe(
            (result: any) => {
                this.liveLink = result.liveLink; // result.livelink is added as part of this.systemPreferences.getLiveUrl above
                this.headerTitle = result.title || '';
            },
            (err) => {
                console.log('there has been an error');
            }
        );
}

systemPreferences.service.ts:

const CACHE_SIZE = 1;

export class SystemPreferences {
    private $cache: Observable<Object>

    private requestConfig() {
         return this.http.get("/api/some/endpoint").pipe(
             map(response => response.value)
         );
    }

    public getPreferences() {
        if (!this.cache$) {
            this.cache$ = this.requestConfig().pipe(
             shareReplay(CACHE_SIZE)
            );
        }

        return this.cache$;
    }

    public getLiveUrl(urls: any) {
        let promises = [];

        urls.forEach((url) => {
           promises.push(this.http.get(url + 'some/endpoint/')); 
        });

        const results = forkJoin(promises) {
            .subscribe((data: any) => {
                return this.getBest(data);
            }
        }
    }

    public getBest(data: any) {
        // Loops through data, and returns a single URL as a string
        // 'http//www.thebesturltouse.com'
    }
}

更新:

嘗試按照建議返回第二個observable,如下所示,與上面的類型void錯誤相同。

cart.component.ts

ngOnInit() {
    this.systemPreferences.getPreferences()
        .pipe(
            .switchMap((result: any) => {
               return this.systemPreferences.getLiveUrl(result['regionUrls']);
            }))
        .subscribe(
            (result: any) => {
                this.liveLink = result.liveLink; // result.livelink is added as part of this.systemPreferences.getLiveUrl above
                this.headerTitle = result.title || '';
            },
            (err) => {
                console.log('there has been an error');
            }
        );
}

systemPreferences.service.ts:

const CACHE_SIZE = 1;

export class SystemPreferences {
    private $cache: Observable<Object>
    private $switchObs: Observable<Object> 

    private requestConfig() {
         return this.http.get("/api/some/endpoint").pipe(
             map(response => response.value)
         );
    }

    public getPreferences() {
        if (!this.cache$) {
            this.cache$ = this.requestConfig().pipe(
             shareReplay(CACHE_SIZE)
            );
        }

        return this.cache$;
    }

    public getLiveUrl(urls: any) {
        let promises = [];

        urls.forEach((url) => {
           promises.push(this.http.get(url + 'some/endpoint/')); 
        });

        const results = forkJoin(promises) {
            .subscribe((data: any) => {
                this.$switchObs = this.getBest(data);
                return this.$switchObs;
            }
        }
    }

    public getBest(data: any) {
        // Loops through data, and returns a single URL as a string
        // 'http//www.thebesturltouse.com'
    }
}

更新到多個switchMaps

cart.component.ts

ngOnInit() {
    this.systemPreferences.getPreferences()
        .pipe(
            .switchMap((result: any) => {
               return this.systemPreferences.getLiveUrl(result['regionUrls']);
            }),
            .switchMap((liveRegion: any) => {
               return this.systemPreferences.getBest(liveRegion);
            }))
        .subscribe(
            (bestUrl: String) => {
                console.log('best');
                console.log(bestUrl);
            },
            (err) => {
                console.log('there has been an error');
            }
        );
}

systemPreferences.service.ts:

const CACHE_SIZE = 1;

export class SystemPreferences {
    private $cache: Observable<Object>
    private $switchObs: Observable<String> 

    private requestConfig() {
         return this.http.get("/api/some/endpoint").pipe(
             map(response => response.value)
         );
    }

    public getPreferences() {
        if (!this.cache$) {
            this.cache$ = this.requestConfig().pipe(
             shareReplay(CACHE_SIZE)
            );
        }

        return this.cache$;
    }

    public getLiveUrl(urls: any) {
        let promises = [];

        urls.forEach((url) => {
           promises.push(this.http.get(url + 'some/endpoint/')); 
        });

        return forkJoin(promises);
    }

    public getBest(data: any) {
        // Loops through data, and returns a single URL as a string
        // 
        return this.$switchObs; // = 'http//www.thebesturltouse.com'
    }
}

有了上面的內容,在console.log('best')/ console.log(bestUrl)上,我看到:

'best'
h
'best'
t
'best'
t
'best'
p
'best'
:
'best'
/
'best'
/
'best'
w
'best'
w
'best'
w
'best'
.
'best'
b
etc etc etc

而不僅僅是字符串http // www.thebesturltouse.com


更新。

在multi switchMap示例中,如果我返回Obserbable.of(this。$ switchObs); 我得到了預期的單字符串URL。

這並不是解決這個問題的最佳方法。

該問題與switchMap運算符本身switchMap 事實上,你的getLiveUrl方法屬於void類型。 switchMap需要一個返回observable作為輸入參數的函數。 所以你希望getLiveUrl返回一個observable。 為了實現這一點,代碼可能看起來像這樣(注意我不是100%確定getBest實際上在做什么,這可能會影響解決方案。):

 public getLiveUrl(urls: any) {
        let promises = [];

        urls.forEach((url) => {
           promises.push(this.http.get(url + 'some/endpoint/')); 
        });

        return forkJoin(promises).pipe(
           map(data => this.getBest(data))
        );
    }

我仍然不能100%確定你實際上想要實現的目標,但我希望這會對你有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM