在 React TypeScript 中使用异步等待和尝试捕获子句处理 HTTP 错误

Handling HTTP error with async await and try and catch clause in react typescript

我有以下代码!

import React, { useState } from "react";

function App() {
const [movies, setMovies] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>();
 async function fetchMoviesHandler() {
    setIsLoading(true);
    setError(null);
try {
      const response = await fetch("https://swapi.dev/api/film/");

      const data = await response.json();
const transformedMovies = data.results.map((movieData: any) => {
        return {
          id: movieData.episode_id,
          title: movieData.title,
          openingText: movieData.opening_crawl,
          releaseDate: movieData.release_date,
        };
      });
setMovies(transformedMovies);
} catch (err: any) {
setError(err.Message);
      console.log(err);
    }
    setIsLoading(false);
  }
return (
    <React.Fragment>
      <section>
        <button onClick={fetchMoviesHandler}>Fetch Movies</button>
      </section>
      <section>
        
        {!isLoading && movies.length > 0 && <p>Movies fetched!</p>}
        {!isLoading && movies.length === 0 && !error && <p>Found no movies.</p>}
        {!isLoading && error && <p>{error}</p>}
        {isLoading && <p>Loading...</p>}
      </section>
    </React.Fragment>
  );
}

export default App;

这里的 URL 不正确,会抛出 404 错误,我希望显示该错误消息。当我 console.log 错误消息显示在控制台上但错误消息未显示在网页上。如果有人能帮我解决这个问题,我将不胜感激。

Fetch docs可以看出:

The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead [...] the Promise will resolve normally (with the ok property of the response set to false if the response isn’t in the range 200–299)

因此 fetchMoviesHandler 中的 catch 子句不会在您收到 404 响应时立即执行,它只会在您尝试从响应中解析正文时执行 (const data = await response.json()), 因为那里没有 json 可以解析。那是错误实际上被抛出并被捕获的时候,但是上面没有 Message 属性,所以没有什么可显示的:内置错误对象上的 属性 是 message.

为了处理这种情况,您应该检查 HTTP 响应中的 ok 属性 并抛出特定错误。像这样:

async function fetchMoviesHandler() {
    setIsLoading(true);
    setError(null);
    try {
      const response = await fetch('https://swapi.dev/api/film/');
      if (!response.ok) {
        throw new Error('Something went wrong');
      }
      const data = await response.json();
      const transformedMovies = data.results.map((movieData: any) => {
        return {
          id: movieData.episode_id,
          title: movieData.title,
          openingText: movieData.opening_crawl,
          releaseDate: movieData.release_date,
        };
      });
      setMovies(transformedMovies);
    } catch (err: any) {
      setError(err.message);
      console.log(err);
    }
    setIsLoading(false);
  }

setError 应该是 setError(err.message) 消息中的 m 应该是小写的。很遗憾,如果您使用 VSCode 它不会显示任何错误。