emitter 增强 多条件触发

本文深入探讨了事件驱动编程模型的实现方式,通过定义事件监听器、触发事件和管理监听者,展示了如何创建一个轻量级且高效的消息传递系统。文章详细解释了事件注册、事件触发、事件监听的一次性和多次性,以及如何处理事件冒泡等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1 ;(function(global ,undefined){
 2     var evts = {}
 3         ,onceTag = '__event_once'
 4     function emit(event ){
 5         var args = util.toArray(arguments , 1)
 6         if (!(event in evts)) return
 7         var _dels = []
 8         for (var i = 0 , j = evts[event].length ; i < j ;i ++){
 9             var cbk = evts[event][i]
10             if (!cbk) return
11             cbk.apply(null , args)
12             if (cbk[onceTag])  { evts[event][i] = null ; _dels.push[i]}
13         }
14         for (var i = _dels.length -1 ; i>=0 ; i--) evts[event].splice(_dels[i] , 1)
15     }
16 
17     function addMultiCon(event , listener){
18         var once = true
19         event.sort()
20         addListener(event.join('|') , listener , once)
21         var eventBubbles = []
22         function tinOpener(evt){
23             eventBubbles.push(evt)
24             if (eventBubbles.length >=  event.length) {
25                 eventBubbles.sort()
26                 emit(eventBubbles.join('|'))
27             }
28         }
29 
30         for (var i = 0 ; i < event.length;i ++){
31             addListener(event[i] , tinOpener.bind(null, event[i]) , once)
32         }
33     }
34 
35     function addListener(event , listener , once){
36         if (util.isArray(event)) return addMultiCon(event , listener)
37 
38 
39         if (!(event in evts)) evts[event] = []
40         if (once) listener[onceTag] = true
41         evts[event].push(listener)
42     }
43 
44     function removeListener(event, listener){
45         if (!listener) {
46             delete evts[event]
47             return
48         }
49         for (var i = 0 , j = evts[event].length ; i < j ;i ++){
50             if (evts[event][i] === listener) {  evts[event].splice(i, 1) ; break}
51         }
52     }
53 
54     function listeners(event){
55         return evts[event]
56     }
57     global.emitter = {
58         on : addListener
59         ,once : function(event , listener){
60                 addListener(event , listener , true)
61                 }
62         ,emit : emit
63         ,listeners : listeners
64     }
65 })(this)
 function toArray(colletions ,offset){
    return Array.prototype.slice.call(colletions , offset || 0)
}

 

 

 

emitter.on(['test','test2'] , function(){
   console.log('test is fired')
})

emitter.emit('test')

emitter.emit('test2')

转载于:https://www.cnblogs.com/vaal-water/p/3949359.html

package fn.server.controller; import fn.server.message.MessageStorageManager; import fn.server.message.SseConnectionManager; import fn.server.message.SseMessageService; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import org.springframework.beans.factory.annotation.Autowired; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @RestController @Slf4j @RequestMapping("/sse") public class SseController { @Autowired private SseConnectionManager connectionManager; @Autowired private MessageStorageManager storageManager; @Autowired private SseMessageService messageService; /** * 用户建立SSE连接 */ @GetMapping(value = "/connect/{userId}") public SseEmitter connect( @PathVariable String userId, @RequestParam(required = false) String companyId, HttpServletResponse response) { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "text/event-stream;charset=UTF-8"); SseEmitter emitter = new SseEmitter(TimeUnit.MINUTES.toMillis(60)); // 60分钟超时 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); // 每30秒发送一次心跳 ScheduledFuture<?> heartbeatFuture = executor.scheduleAtFixedRate(() -> { try { emitter.send(SseEmitter.event().comment("heartbeat")); } catch (IOException e) { log.warn("Heartbeat failed for user {}: {}", userId, e.getMessage()); } }, 0, 30, TimeUnit.SECONDS); // 绑定用户连接 connectionManager.addEmitter(userId, companyId, emitter); // 发送初始数据 try { storageManager.sendPendingMessages(userId, messageService); emitter.send("中文信息".getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { log.error("Initial data send failed for user {}: {}", userId, e.getMessage()); } // 连接完成或超时处理 emitter.onCompletion(() -> { heartbeatFuture.cancel(true); executor.shutdown(); connectionManager.removeEmitter(userId); }); emitter.onTimeout(() -> { emitter.complete(); connectionManager.removeEmitter(userId); }); return emitter; } @GetMapping("/logout/{userId}") public String logout(@PathVariable String userId) { try { // 断开用户的SSE连接 connectionManager.removeEmitter(userId); return "User " + userId + " logged out and connection closed."; } catch (Exception e) { e.printStackTrace(); return "Error while logging out user " + userId; } } } 这段代码老是报错2025-03-10 10:50:51.114 WARN 9328 --- [ol-102-thread-1] fn.server.controller.SseController : Heartbeat failed for user e82c24aa-d619-4754-8d56-ef58d48c028d: java.io.IOException: 你的主机中的软件中止了一个已建立的连接。
03-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值