前端调用async fetch获取后端API数据仅返回部分内容问题
前端Fetch请求仅接收部分后端API返回数据的排查与解决
问题场景
开发课程项目时,前端用JavaScript的async fetch调用后端Java API,仅能收到部分返回数据:后端本应返回包含status和content的完整JSON,但前端只拿到{"status": "success"}。Postman调用该API完全正常,前端接收异常。
预期后端返回
{ "status": "success", "content": [ { "name": "ABC", "key": "123456" } ] }
前端实际接收
{"status": "success"}
相关代码
前端JavaScript代码
export async function getObjectsFromS3(data) { const response = await fetch(url, { method: "GET", headers: { "Authorization": `Basic ${btoa("user:password")}` } }); if (!response.ok) { throw new Error(response.status); } const result = await response.json(); return result }
后端Java代码
@RestController @RequestMapping("/users") public class S3Controller { @Autowired S3Service s3Service; @GetMapping("/{userName}/objects") public String listObjects(@PathVariable String userName, @RequestParam String prefix) { AuthenticationUtil.authorizeUser(userName); String jsonString = ""; JSONObject jo = new JSONObject(); JSONArray ja = new JSONArray(); ja.put("key"); ja.put("name"); ja.put("size"); ja.put("type"); try { List<S3Object> objects = s3Service.listObjects(prefix); for (S3Object object : objects) { String suffix = object.key().replace(prefix, ""); String[] suffixDir = suffix.split("/"); if ((suffixDir.length == 1 && suffixDir[0] !== "")) { String type, name, key; key = object.key(); if (key.charAt(key.length() - 1) === '/') type = "folder"; else type = "file"; name = suffixDir[suffixDir.length - 1]; jsonString += object.key() + "," + name + "," + String.valueOf(object.size()) + "," + type + "\n"; } } jo.put("status", "success"); jo.put("content", CDL.toJSONArray(ja, jsonString)); } catch (Exception e) { jo.put("status", "error"); jo.put("message", "Error when listing files: " + e.getMessage()); } return jo.toString(); } }
问题排查与解决方法
1. 修正Java语法错误
原代码中判断字符串非空用了!==,这是JavaScript语法,Java中字符串不等于应改为!"".equals(suffixDir[0])(避免空指针风险)。虽然Postman调用正常,但语法错误可能导致逻辑异常,先修正此问题。
2. 替换CDL拼接JSON的方式
CDL.toJSONArray通过字符串拼接生成JSON数组,容易出现格式错误(比如换行未转义),导致前端response.json()解析失败,只解析了前面的status字段。建议直接构建JSON对象数组:
// 替换原循环中的字符串拼接逻辑 JSONArray contentArray = new JSONArray(); for (S3Object object : objects) { String suffix = object.key().replace(prefix, ""); String[] suffixDir = suffix.split("/"); if (suffixDir.length == 1 && !"".equals(suffixDir[0])) { String type, name, key; key = object.key(); type = key.charAt(key.length() - 1) == '/' ? "folder" : "file"; name = suffixDir[suffixDir.length - 1]; JSONObject item = new JSONObject(); item.put("key", key); item.put("name", name); item.put("size", object.size()); item.put("type", type); contentArray.put(item); } } jo.put("content", contentArray);
3. 前端添加JSON解析错误捕获
当前代码仅判断HTTP状态码,未捕获JSON解析异常。添加捕获逻辑,打印原始响应文本确认后端返回是否完整:
export async function getObjectsFromS3(data) { const response = await fetch(url, { method: "GET", headers: { "Authorization": `Basic ${btoa("user:password")}` } }); if (!response.ok) { throw new Error(response.status); } try { const result = await response.json(); return result; } catch (parseError) { console.error("JSON解析失败:", parseError); const rawText = await response.text(); console.log("原始响应文本:", rawText); throw parseError; } }
4. 确保后端响应头正确
后端直接返回String类型时,Spring可能未正确设置Content-Type: application/json,导致前端解析异常。可以改为返回JSONObject或手动设置响应头:
// 方式1:返回JSONObject,Spring自动处理Content-Type @GetMapping("/{userName}/objects") public JSONObject listObjects(@PathVariable String userName, @RequestParam String prefix) { // 逻辑不变,最后直接返回jo return jo; } // 方式2:手动设置响应头 @GetMapping("/{userName}/objects") public ResponseEntity<String> listObjects(@PathVariable String userName, @RequestParam String prefix) { // 逻辑不变 return ResponseEntity.ok() .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .body(jo.toString()); }
内容的提问来源于stack exchange,提问作者Henry
相关产品推荐
相关产品推荐

