如何强制Socket.IO按顺序执行forEach循环中的emit操作?
解决Socket.IO forEach循环中emit串行执行的问题
问题根源
你代码里用forEach同步遍历数组时,会一次性触发所有socket.emit请求——因为socket.timeout().emit()是非阻塞操作,所有请求会同时发送、超时也会同时触发,服务器无法及时处理全部请求,最终只有少数生效。
解决方案
要实现顺序执行(前一个emit的超时完成后再发送下一个),可以用以下两种方式:
方式1:使用async/await + Promise(推荐)
将回调改为async函数,用for...of遍历数组,把每个emit操作包装成Promise,等待超时回调触发后再进入下一次循环:
socket.on("setPermissions", async function() { // Example: 1;2;3;4;5 const episodes = episodesString.split(';'); if (episodes.length > 1) { for (const episode of episodes) { console.log(episode); // 包装emit为Promise,等待超时完成后继续 await new Promise((resolve) => { socket.timeout(5000).emit("queue", { 'type':'cm', 'id': episode, 'pos':'end', 'temp':false, 'duration':0 }, () => { // 无论成功、超时还是失败,都触发resolve,继续下一个请求 resolve(); }); }); } } });
方式2:递归调用
如果环境不支持async/await,可以用递归函数逐个发送请求,当前请求的超时回调触发后再调用下一个:
socket.on("setPermissions", function() { const episodes = episodesString.split(';'); if (episodes.length > 1) { let currentIndex = 0; const sendNextEpisode = () => { if (currentIndex >= episodes.length) return; const episode = episodes[currentIndex]; console.log(episode); socket.timeout(5000).emit("queue", { 'type':'cm', 'id': episode, 'pos':'end', 'temp':false, 'duration':0 }, () => { currentIndex++; sendNextEpisode(); }); }; sendNextEpisode(); } });
效果说明
两种方式都能实现:日志依次输出(1、2、3...),每次emit请求发送后等待5秒超时,再执行下一个请求,确保服务器能逐个处理。
内容的提问来源于stack exchange,提问作者CodingWolf
相关产品推荐
相关产品推荐

