后端异步方法实施结束通知前端
Situation:
异步任务的执行可能非常耗时或者需要依赖其他资源或系统的响应,因此在执行这些任务时,前端客户端不能一直等待其执行完毕。这时候,异步任务的执行一般会放在后端服务器上,等到任务执行完毕后,后端需要将执行结果通知给前端客户端。
常用的方案
轮询:
方式:
前端客户端定时向服务器发出请求,询问任务是否已经完成,如果完成则返回结果给前端
优点与不足
- 优点
- 实现简单无需特殊的服务支持
- 易于控制频率,避免服务器过载
- 容错性较强,如果轮训失败,可进行有效的重试
- 缺点
- 增加了带宽损耗
- 增加了负载与网络流量
- 互动性不足
websocket
方式:
WebSocket:使用WebSocket技术,建立一个全双工通信的通道,当任务完成时,后端服务器可以通过WebSocket主动向前端客户端发送消息。
优点与不足
- 优点
- 实时性好,可以实现双向通信;
- 对于推送式的信息(例如即时消息),效果很好
- 只需要建立一个持久性连接,可以降低网络负载和服务器负载
- 不足
- 实现难度较高
- 如果消息类型、服务端地址发生变化,需要重新连接;
- 需要对于运行环境以及网络状况进行更多考虑
实例
🟥 使用轻量级的SimpMessagingTemplate 发送信息
SimpMessageTemplate 基础教程
- 全句配置socket 代理适配
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket").setAllowedOriginPatterns("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
}
}
- 注入
SimpMessagingTemplate并调用其convertAndSend()方法发送消息
public void importTaskRun(Long daDataImportTaskId) {
// 获取任务信息
DaDataImportTask daDataImportTask = daDataImportTaskMapper.selectDaDataImportTaskByDaDataImportTaskId(daDataImportTaskId);
dataSourceManagerUtils.dataImport(daDataImportTask).whenCompleteAsync((result, throwable) -> {
if (throwable != null) {
daDataImportTask.setDaDataImportStatus("3");
daDataImportTaskMapper.updateDaDataImportTask(daDataImportTask);
} else {
daDataImportTask.setDaDataImportStatus("2");
daDataImportTaskMapper.updateDaDataImportTask(daDataImportTask);
}
messagingTemplate.convertAndSend("/topic/message",daDataImportTask.getDaDataImportTaskId() );
});
}
3.前端构建
mounted() {
this.socket = new SockJS('http://localhost:16868/websocket');
this.stompClient = Stomp.over(this.socket);
this.stompClient.connect({},
this.onConnected,
this.onError
);
},
// 释放socket连接,与订阅
beforeDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
if (this.stompClient) {
this.stompClient.disconnect();
}
},
// socket 链接初始化
onConnected() {
this.subscription = this.stompClient.subscribe('/topic/message', this.onSubMessage);
},
onError(error) {
console.log("There is something wrong in socket")
},
// 订阅后端消息
onSubMessage(data) {
console.log('Data received:', data);
this.updateTaskExecuteButtonStatusByIndex(data.body)
},
// 更新任务列表中执行按钮的状态
updateTaskExecuteButtonStatusByIndex(rowIndex) {
// 重新获取数据列表
this.getList()
},
消息队列
将异步任务的结果封装为消息,发送到消息队列中,后端服务器监听队列,当任务完成后即可将结果传递给前端客户端。