如何通过HTTP获取URL状态?请求facebook.com出现404问题排查
问题分析与修复方案
核心问题1:URL格式错误
当你请求facebook.com时,由于没有指定协议头(https://或http://),ky会将其识别为相对路径,自动拼接当前页面的基础域名(即你的本地开发地址http://localhost:5173),最终请求地址变成http://localhost:5173/www.facebook.com,自然返回404错误。而https://jsonplaceholder.typicode.com/users因为是完整的绝对路径(带协议和域名),所以能正常请求。
核心问题2:自定义Hook的错误用法
你将useFetchStatus定义为async函数,但React/Preact的自定义Hook必须是同步函数——Hook规则要求Hook必须在组件顶层同步调用,async函数返回的是Promise,无法被Hook系统正确处理,当前写法虽能临时运行,但会违反Hook规则,埋下潜在bug。
修复代码
1. 重构请求函数(去掉Hook标识,改为普通异步工具函数)
import ky from "ky"; // 自动补全URL协议头,避免相对路径问题 const normalizeUrl = (url: string) => { if (!/^https?:\/\//i.test(url)) { return `https://${url}`; } return url; }; // 改为普通异步函数,而非Hook export const fetchStatus = async (url: string) => { try { const response = await ky.get(normalizeUrl(url)); return response.status; } catch (error) { // 捕获HTTP错误,返回对应状态码;非HTTP错误返回-1标记 if (error instanceof ky.HTTPError) { return error.response.status; } return -1; } };
2. 修正组件中的调用逻辑
import { useEffect, useState } from "preact/hooks"; import { fetchStatus } from "./hooks/hooks"; export const App = () => { const [status, setStatus] = useState(0); // 测试:即使输入不带协议的域名也能正常处理 const url = "facebook.com"; useEffect(() => { const interval = setInterval(async () => { const currentStatus = await fetchStatus(url); setStatus(currentStatus); }, 1000); // 清理定时器 return () => clearInterval(interval); }, [url]); // 将url加入依赖数组,避免闭包导致的旧值问题 return <>Status: {status}</>; };
额外说明
- 加入
normalizeUrl函数后,无论输入的是带协议的完整URL还是纯域名,都会被转换为合法的绝对路径,彻底解决本地域名拼接问题。 - 添加
try/catch是为了处理请求失败场景(如网络错误、4xx/5xx状态码),避免定时器因未捕获错误意外终止。 - 移除
useFetchStatus的Hook标识,因为它没有使用任何React/Preact内置Hook,不需要以Hook形式存在。
内容的提问来源于stack exchange,提问作者user21175044
相关产品推荐
相关产品推荐

