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

Java Spring异步调用错误处理:如何通知React前端操作失败?

异步场景下通知前端操作失败的解决方案

你不需要退回到同步代码,异步执行时同样可以把错误信息传递给前端,下面是两种实用方案:


方案一:任务ID轮询(适合新手,实现简单)

核心思路是:API先返回一个任务ID给前端,前端定期查询任务状态,后端在异步执行完成后更新任务的成功/失败状态及错误信息。

1. 后端实现步骤

(1)创建任务状态实体

用来记录异步任务的执行情况:

@Entity
public class TaskStatus {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private String taskId;
    private String status; // 可选值:PENDING(处理中)、SUCCESS(成功)、FAILED(失败)
    private String errorMessage;
    private Long studentId; // 关联已创建的学生ID(成功时填充)
    
    // 省略getter、setter
}

(2)修改API接口

返回任务ID,同时启动异步任务:

@PostMapping("/createStudent")
public ResponseEntity<Map<String, String>> createStudent(@RequestBody Student student) {
    // 初始化任务状态为"处理中"
    TaskStatus task = new TaskStatus();
    task.setStatus("PENDING");
    taskStatusRepository.save(task);
    
    // 异步执行保存逻辑,传入任务ID
    studentService.createAsyncStudent(student, task.getTaskId());
    
    // 返回任务ID给前端
    return ResponseEntity.ok(Map.of("taskId", task.getTaskId()));
}

// 新增查询任务状态的API
@GetMapping("/task/{taskId}")
public ResponseEntity<TaskStatus> getTaskStatus(@PathVariable String taskId) {
    TaskStatus task = taskStatusRepository.findById(taskId)
            .orElseThrow(() -> new RuntimeException("任务不存在"));
    return ResponseEntity.ok(task);
}

(3)异步服务方法更新任务状态

@Async
public void createAsyncStudent(Student student, String taskId) {
    TaskStatus task = taskStatusRepository.findById(taskId).get();
    try {
        // 原有的学生保存逻辑
        Student createdStudent = studentRepository.save(student);
        task.setStatus("SUCCESS");
        task.setStudentId(createdStudent.getId());
    } catch (Exception e) {
        // 捕获错误,更新任务状态和错误信息
        task.setStatus("FAILED");
        task.setErrorMessage(e.getMessage());
    } finally {
        taskStatusRepository.save(task);
    }
}

2. 前端React逻辑

拿到任务ID后定时查询状态:

async function submitStudentForm(studentData) {
  // 提交创建请求
  const createRes = await fetch('/createStudent', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(studentData)
  });
  const { taskId } = await createRes.json();

  // 轮询查询任务状态
  const statusInterval = setInterval(async () => {
    const statusRes = await fetch(`/task/${taskId}`);
    const taskStatus = await statusRes.json();
    
    if (taskStatus.status === 'SUCCESS') {
      clearInterval(statusInterval);
      alert(`学生创建成功,ID:${taskStatus.studentId}`);
    } else if (taskStatus.status === 'FAILED') {
      clearInterval(statusInterval);
      alert(`创建失败:${taskStatus.errorMessage}`);
    }
  }, 1000); // 每秒查询一次,可根据实际调整间隔
}

方案二:WebSocket主动推送(实时性更强)

核心思路是:前端和后端建立WebSocket连接,后端异步任务出错时,主动向对应的前端推送错误信息。

1. 后端WebSocket配置

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 注册WebSocket处理器,允许跨域
        registry.addHandler(new TaskErrorHandler(), "/task-notify").setAllowedOrigins("*");
    }
}

// WebSocket消息处理器
public class TaskErrorHandler extends TextWebSocketHandler {
    // 存储客户端会话,key为会话ID
    private static final Map<String, WebSocketSession> clientSessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        clientSessions.put(session.getId(), session);
    }

    // 提供静态方法,向指定客户端推送错误信息
    public static void pushError(String sessionId, String errorMsg) {
        WebSocketSession session = clientSessions.get(sessionId);
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(errorMsg));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2. 修改创建学生API

@PostMapping("/createStudent")
public ResponseEntity<Void> createStudent(@RequestBody Student student, HttpServletRequest request) {
    // 获取当前请求的会话ID,用来定位推送的客户端
    String sessionId = request.getSession().getId();
    studentService.createAsyncStudent(student, sessionId);
    return ResponseEntity.ok().build();
}

3. 异步服务方法推送错误

@Async
public void createAsyncStudent(Student student, String sessionId) {
    try {
        studentRepository.save(student);
    } catch (Exception e) {
        // 向前端推送错误信息
        TaskErrorHandler.pushError(sessionId, "学生创建失败:" + e.getMessage());
    }
}

4. 前端WebSocket连接逻辑

useEffect(() => {
  // 建立WebSocket连接
  const socket = new WebSocket('ws://localhost:8080/task-notify');
  
  // 接收后端推送的消息
  socket.onmessage = (event) => {
    alert(`后端通知:${event.data}`);
  };

  // 组件卸载时关闭连接
  return () => socket.close();
}, []);

注意事项

  • 轮询方案要注意清理过期的任务状态数据,避免数据库冗余。
  • WebSocket方案需要处理连接断开重连的情况,确保消息不丢失。
  • 两种方案都可以配合全局异常处理器,统一捕获异步任务中的异常。

内容的提问来源于stack exchange,提问作者random55645

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:50:27