如何在 Angular 5(或>4.3)中将 Http 转换为 HttpClient?

4

我有一个使用Http的工作代码,我想学习如何将其转换为使用最新的HttpClient。

我已经完成了以下步骤:

  • 在App.module.ts中:导入{ HttpClientModule } from "@angular/common/http";
  • 将HttpClientModule添加到imports数组中
  • 在以下服务文件(见下文)中:导入{ HttpClient } from "@angular/common/http";
  • 在构造函数中注入HttpClient而不是Http(用HttpClient替换Http)。

现在,以下步骤我无法正确操作(如何重写return this.http.get(queryUrl)..

有什么想法吗?

...

使用Http的工作代码:

import { Injectable, Inject } from "@angular/core";
import { Http, Response } from "@angular/http";
import { Observable } from "rxjs/Observable";
import { SearchResult } from "../models/search-results.model";

export const YOUTUBE_API_KEY = "AIzaSyCIYsOjnkrIjZhVCFwqNJxe1QswhsliciQ";
export const YOUTUBE_API_URL = "https://www.googleapis.com/youtube/v3/search";

@Injectable()
export class YoutubeSearchService {
  constructor(
    private http: Http,
    @Inject(YOUTUBE_API_KEY) private apiKey: string,
    @Inject(YOUTUBE_API_URL) private apiUrl: string,
  ) {}

  search(query: string): Observable<SearchResult[]> {
    const params: string = [
      `q=${query}`,
      `key=${this.apiKey}`,
      `part=snippet`,
      `type=video`,
      `maxResults=10`,
    ].join("&");
    const queryUrl = `${this.apiUrl}?${params}`;

    return this.http.get(queryUrl).map((response: Response) => {
      return (<any>response.json()).items.map(item => {
        // console.log("raw item", item); // uncomment if you want to debug
        return new SearchResult({
          id: item.id.videoId,
          title: item.snippet.title,
          description: item.snippet.description,
          thumbnailUrl: item.snippet.thumbnails.high.url,
        });
      });
    });
  }
}

这里是更新后的代码。

新的HttpClient自动假设您返回的是json,所以不再需要response.json()。我建议阅读文档(https://angular.io/guide/http)。它应该包含您所需的一切。 - LLai
你遇到了什么错误或问题? - Aravind
2个回答

7

响应类型现在由 responseType 选项控制,默认为 json。这消除了 .map((response: Response) => response.json()) 行。

HttpClient 方法是通用的,响应对象类型默认为 Object。可以提供类型以加强类型检查:

return this.httpClient.get(queryUrl).map(response => {
  return response.items.map(
    item =>
      new SearchResult({
        id: item.id.videoId,
        title: item.snippet.title,
        description: item.snippet.description,
        thumbnailUrl: item.snippet.thumbnails.high.url,
      }),
  );
});

将服务实例重命名为httpClient有益于避免与Http实例混淆。

当您想使用该服务时,您需要订阅它。

假设在组件中注入了YouTubeSearchService,则可以说YouTube是注入的服务。

  queryYoutube() {
    this.youtube.search("Rio de Janeiro").subscribe(data => console.log(data));
  }

嗨@estus,感谢你的回答!我为更改后的代码创建了一个fiddle(https://jsfiddle.net/u00pvkvs/1/),请在此处查看:我遵循了你的建议,请在此处查看: // 属性“items”在类型“Object”上不存在。 - Isak La Fleur
2
这就是答案所解释的。考虑提供一个适当的类型,比如ISearchResultItems。当然你可以使用any,但这会消除类型安全性。 - Estus Flask

1
在Angular 5中,您可以在.pipe内使用.map函数两次来完成与先前版本相同的操作:
getCoinRankings () : Observable<Coinobject[]>{
  return this.http.get<Coinobject[]>(this.coinmarketcapAPI)
    .pipe(
      map(x => x.map(data => new Coinobject(data))),
      tap(coinrankings => console.log(`fetched coinrankings`)),
      catchError(this.handleError('getCoinrankings',[]))
    )
}

x = request.json() -> 整个json响应 data = json数组中的单个项。 在我的示例中,我使用了一个构造函数,手动将json映射到所需的属性,但你也可以像这样做。

return this.httpClient.get<Object[]>(queryUrl).pipe(
    map(response => response.map(data => new SearchResult{
        id: item.id.videoId,
        title: item.snippet.title,
        description: item.snippet.description,
        thumbnailUrl: item.snippet.thumbnails.high.url,
      })),
    tap(...),
    catchError(...)
    )
}

当然,使用已弃用的模块不会损害您的应用程序...(但请随时纠正我)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接