如何让PHP返回错误供JS Promise的catch捕获?跨域预检报错解析
问题解答:通过PHP header()让AJAX Promise的catch捕获错误
这个需求是完全可行的!你现在遇到的报错问题,根源是跨域预检请求(OPTIONS)没有正确处理,而不是用header返回错误状态码的思路有问题。
为什么当前代码会报错?
跨域请求时,浏览器会先自动发送一个OPTIONS类型的预检请求,用来确认服务器是否允许后续的实际请求(比如你的GET请求)。你的PHP代码没有专门处理OPTIONS请求,导致预检请求进来后,会执行到业务逻辑判断$_SESSION['user_id'] == 0,返回了500错误状态码——浏览器看到预检请求返回错误,就直接终止了后续流程,根本不会发送实际的GET请求,自然你的Promise catch也不会触发。
解决方案:先处理预检请求,再返回标准HTTP错误码
- 优先处理OPTIONS预检请求:在PHP代码最开头添加逻辑,当请求方法是OPTIONS时,直接返回200状态码和必要的CORS头,不要执行后续业务逻辑。
- 使用标准HTTP错误状态码:尽量避免自定义像1337这样的状态码,虽然浏览器能识别,但不符合HTTP规范,部分客户端可能处理异常。推荐用400(请求错误)、401(未授权)、403(禁止访问)、500(服务器错误)这类标准码。
修正后的完整PHP代码
<?php session_start(); $_SESSION['user_id'] = 1; // 专门处理OPTIONS预检请求 if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Credentials: true"); header("Access-Control-Allow-Methods: GET,HEAD,OPTIONS,POST,PUT"); header("Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"); http_response_code(200); exit; } // 为实际请求设置CORS头 header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Credentials: true"); header("Access-Control-Allow-Methods: GET,HEAD,OPTIONS,POST,PUT"); header("Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"); if ($_SESSION['user_id'] == 0) { header('Content-Type: application/json'); print json_encode(["test" => 123]); } else { // 使用标准的403禁止访问状态码 http_response_code(403); header('Content-Type: application/json; charset=UTF-8'); die(json_encode(array('message' => 'ERROR: User ID is not valid', 'code' => 403))); } ?>
修正后的JavaScript代码(修复语法错误,优化catch逻辑)
axios.get('loginStatus.php', { crossDomain: true }) .then(function (response) { console.log('Success response:', response); }) .catch(function (error) { if (error.response) { // 服务器返回了错误响应,可以拿到错误详情 console.log('Error message:', error.response.data.message); console.log('Error status code:', error.response.status); } else { // 请求发送失败(比如网络问题) console.log('Request failed:', error.message); } });
补充说明
当然,你也可以选择始终返回200状态码,在JSON响应里携带错误标识(比如{ "success": false, "message": "xxx" }),然后在then方法里判断处理。但用HTTP状态码的方式更符合RESTful设计规范,也能让Promise的catch自动捕获错误,代码逻辑更清晰。
内容的提问来源于stack exchange,提问作者Kalreg
相关产品推荐
相关产品推荐

