You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Angular新手调用维基百科API获取4条标题数据时的报错问题排查

Hey there! Let’s break down the issues in your Angular code step by step—since you’re new to this, these are totally common bumps to hit, so no worries 😊

1. Broken Interface Definition for Wikipedia API Responses

Your Pages interface is hardcoded to a specific page ID (The4101295), but Wikipedia’s API returns a dynamic object where keys are unique page IDs. This means TypeScript can’t properly parse the response data. Here’s the fixed interface:

export interface IWikiItem { 
  batchcomplete?: string; 
  query?: Query; 
}
export interface Query { 
  normalized?: Normalized[]; 
  pages?: { [key: string]: PageDetails }; // Use index signature for dynamic page IDs
}
export interface Normalized { 
  from?: string; 
  to?: string; 
}
export interface PageDetails { // Replace hardcoded ID interface
  pageid?: number; 
  ns?: number; 
  title?: string; 
  pageprops?: Pageprops; 
}
export interface Pageprops { 
  defaultsort?: string; 
  page_image_free?: string; 
  wikibase_item?: string; 
}

2. CORS Error with Wikipedia API

Wikipedia’s API requires an origin=* parameter to allow cross-browser requests. Without it, you’ll get a CORS block. Update your service to use HttpParams for cleaner, safer request building:

import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { IWikiItem } from './IwikiItem';

@Injectable({ providedIn: 'root' })
export class SrvService {
  readonly base_url = 'https://en.wikipedia.org/w/api.php';

  getWiki(title: string) {
    const params = new HttpParams()
      .set('action', 'query')
      .set('prop', 'pageprops')
      .set('format', 'json')
      .set('titles', title)
      .set('origin', '*'); // Fixes CORS issue

    return this.http.get<IWikiItem>(this.base_url, { params });
  }

  constructor(private http: HttpClient) {}
}

3. Incorrect Data Source Handling & Subscription Logic

Your current code loops through titles and creates a new data source on every single request—this is inefficient and has syntax errors. Use forkJoin to wait for all requests to complete, then load all data into the table at once:

import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { forkJoin } from 'rxjs';
import { PageDetails, IWikiItem } from './IwikiItem';
import { SrvService } from './srv.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  dataSource: MatTableDataSource<PageDetails>;
  private titles = ['Wilson_Lumpkin', 'Robert Toombs', 'Saxby Chambliss', 'Wyche Fowler'];

  constructor(private srv: SrvService) {
    // Initialize empty data source first to avoid undefined errors
    this.dataSource = new MatTableDataSource<PageDetails>([]);
  }

  ngOnInit(): void {
    // Create an array of observables for all title requests
    const wikiRequests = this.titles.map(title => this.srv.getWiki(title));

    // Wait for all requests to finish before processing data
    forkJoin(wikiRequests).subscribe({
      next: (responses) => {
        // Extract page data from each response
        const allPages = responses.flatMap(response => {
          if (response.query?.pages) {
            // Convert dynamic page object to an array
            return Object.values(response.query.pages);
          }
          return [];
        });
        // Load data into the table
        this.dataSource.data = allPages;
        console.log('All data loaded:', allPages);
      },
      error: (err) => {
        console.error('Failed to fetch data:', err);
      }
    });
  }
}

4. Quick Notes on Other Fixes

  • Your original code had invalid syntax for setting this.dataSource—the line (this.dataSource: new MatTableDataSource<IWikiItem[data]>); was not valid TypeScript.
  • Initializing the data source upfront prevents undefined errors when the table tries to render before data loads.
  • Using forkJoin ensures you only update the table once all data is ready, instead of multiple partial updates.

内容的提问来源于stack exchange,提问作者meir1meir

火山引擎 最新活动