You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 19:52:40