
在使用JavaScript的fetch API进行网络请求时,一个常见的误解是它会像传统的XMLHttpRequest那样,在遇到HTTP状态码非2xx(如400 Bad Request,500 Internal Server Error)时直接抛出错误。然而,fetch API的设计理念是,只有在网络故障或请求无法完成时才将Promise标记为rejected。对于成功的HTTP响应(即使状态码是4xx或5xx),fetch Promise仍然会被resolve。
在这种情况下,我们需要通过检查Response对象的ok属性来判断请求是否成功(response.ok为true表示HTTP状态码在200-299之间)。如果response.ok为false,通常我们会选择抛出一个错误。然而,直接使用throw Error(response.statusText)会带来一个问题:response.statusText只包含HTTP状态码对应的标准文本(例如,对于400状态码是"Bad Request"),而无法获取服务器在响应体中发送的自定义错误信息。
考虑以下JavaScript代码片段,它尝试处理一个潜在的错误响应:
let btn = document.getElementById('myButton');
btn.addEventListener('click', function(event){
  const fd = new FormData();
  fd.append('user', 'myUserName');
  fetch('/test', {method: 'POST', body: fd})
    .then((response) => {
      if(!response.ok){
        // 这里的 throw Error(response.statusText) 只能获取标准HTTP状态文本
        // 无法获取服务器自定义的错误消息
        throw Error(response.statusText);
      }
      return response.json();
    })
    .then((data) => {
      console.log('data received', data);
    })
    .catch((error) => {
      // 此时 error 仅为 "Error: Bad Request" 或类似内容
      console.log(error);
    });
});为了向前端提供更具体、更友好的错误提示,后端服务通常会在HTTP状态码非2xx时,在响应体中包含一个结构化的错误信息(通常是JSON格式)。例如,一个使用Symfony框架编写的PHP后端控制器可能会这样返回一个自定义错误:
立即学习“PHP免费学习笔记(深入)”;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class MyController
{
  #[Route('/test', name:'test', methods: ['POST'])]
  public function test(Request $req): Response
  {
    // 模拟一个自定义错误,并返回400状态码
    return new JsonResponse(['error' => 'my Custom Error'], 400);
  }
}在这个例子中,即使HTTP状态码是400,响应体中也包含了{'error': 'my Custom Error'}这个关键信息。前端的目标就是捕获这个自定义的JSON对象。
问题的核心在于,当response.ok为false时,Response对象本身仍然包含一个可读的响应体流。我们需要像处理成功响应一样,调用response.json()(如果响应体是JSON)或response.text()(如果响应体是纯文本)来解析这个流,才能获取到服务器发送的自定义内容。
由于response.json()方法返回一个Promise,我们需要等待这个Promise解析完成,才能获取到实际的错误数据。最简洁有效的方法是在if (!response.ok)块中使用await关键字。
以下是修正后的JavaScript代码:
let btn = document.getElementById('myButton');
btn.addEventListener('click', async function(event){ // 注意这里添加了 async
  const fd = new FormData();
  fd.append('user', 'myUserName');
  try {
    const response = await fetch('/test', {method: 'POST', body: fd});
    if (!response.ok) {
      // 关键:等待 response.json() 解析完成,然后抛出解析后的数据
      // 这样,.catch 块就能接收到自定义的错误对象
      throw await response.json();
    }
    const data = await response.json();
    console.log('data received', data);
  } catch (error) {
    // 此时 error 将是服务器返回的自定义错误对象,例如 {error: "my Custom Error"}
    console.log('Error caught:', error);
    // 可以根据 error 对象的结构进行更详细的处理,例如:
    if (error && error.error) {
      console.log('Custom error message:', error.error);
      // alert(error.error); // 提示用户
    } else {
      console.log('Generic error:', error);
    }
  }
});代码解析:
正确处理Fetch API的错误响应,尤其是从非2xx HTTP状态码的响应体中提取自定义错误消息,是构建健壮前端应用的关键一环。通过在if (!response.ok)条件分支中利用await response.json()来解析响应体并抛出,我们可以确保catch块能够接收到后端提供的详细、结构化的错误信息。这种方法不仅提高了错误诊断的效率,也为用户提供了更清晰、更有用的反馈。
以上就是使用Fetch API在JavaScript中获取PHP自定义错误消息的最佳实践的详细内容,更多请关注php中文网其它相关文章!
                        
                        PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号