当前位置:   article > 正文

Vue3前端实现一个本地消息队列(MQ), 让消息延迟消费或者做缓存

Vue3前端实现一个本地消息队列(MQ), 让消息延迟消费或者做缓存

MQ功能实现的具体代码(TsMQ.ts):

  1. import { v4 as uuidx } from 'uuid';
  2. import emitter from '@/utils/mitt'
  3. // 消息类
  4. class Message {
  5. // 过期时间,0表示马上就消费
  6. exp: number;
  7. // 消费标识,避免重复消费
  8. tag : string;
  9. // 消息体
  10. body : any;
  11. constructor( exp: number , body : any ) {
  12. if (exp == 0) {
  13. this.exp = 0;
  14. }else {
  15. this.exp = Date.now().valueOf() + exp;
  16. }
  17. this.body = body;
  18. this.tag = uuidx();
  19. }
  20. }
  21. export default class TsMQ {
  22. static tsMQ : TsMQ;
  23. cache : boolean;
  24. repository : Map<string, any[]>;
  25. /*
  26. 设置只作为缓存使用
  27. */
  28. setCache(cache : boolean) {
  29. this.cache = cache;
  30. }
  31. /*
  32. 获取单列的MQ对象
  33. */
  34. static getInstance() : TsMQ {
  35. if(this.tsMQ == null) {
  36. this.tsMQ = new TsMQ();
  37. }
  38. return this.tsMQ;
  39. }
  40. constructor() {
  41. this.repository = new Map<string,any[]>();
  42. this.cache = false;
  43. setInterval(()=> {
  44. Array.from(this.repository.keys()).forEach( key => {
  45. let poll = this.repository.get(key) as any[];
  46. if(poll.length > 0) {
  47. poll.forEach( item => {
  48. if (item.exp == 0 || item.exp <= Date.now().valueOf() - 100) {
  49. // 如果是作为缓存使用就不会放入mitt就行推送
  50. if(!this.cache) {
  51. emitter.emit(key,item.body);
  52. }
  53. let single : any[] = this.repository.get(key) as any[];
  54. single = single.filter(dispose => {
  55. return dispose.tag !== item.tag;
  56. });
  57. this.repository.set(key,single);
  58. }
  59. });
  60. }
  61. });
  62. },100)
  63. }
  64. /*
  65. * @describe 放消息入队列
  66. * @param queue : string 队列名称
  67. * @param exp : number 消息消费时间
  68. * @param message : any 消息体
  69. */
  70. pushMessage( queue : string , exp : number, message : any ) {
  71. if(this.repository.has(queue)) {
  72. let single : any[] = this.repository.get(queue) as any[];
  73. single.push(new Message(exp,message));
  74. this.repository.set(queue,single);
  75. }else {
  76. let temp = [];
  77. temp.push(new Message(exp,message));
  78. this.repository.set(queue,temp);
  79. }
  80. }
  81. /*
  82. * @describe 直接获取消息,可以配合做本地缓存,就要去掉constructor的轮询中的事件推送
  83. * @param queue : string 队列名称
  84. */
  85. takeMessage( queue : string ) : any {
  86. let single : any[] = this.repository.get(queue) as any[];
  87. if( single && single.length > 0) {
  88. let message = single.shift();
  89. this.repository.set(queue,single);
  90. return message;
  91. }else {
  92. return '队列没有消息!';
  93. }
  94. }
  95. }
提示:其中需要用到三方的uuid和mitt,然后要消息持久化可以用到pinia来让消息持久化,本案列没有采用持久化
uuid的三方包安装命令
npm install uuid
mitt的三方安装命令 
npm install --save mitt 

 其中mitt文件的代码

  1. import mitt from "mitt";
  2. const emitter = mitt();
  3. export default emitter;

使用方式:

投送消息
  1. <script setup lang="ts">
  2. import TsMQ from '@/utils/TsMQ'
  3. import emitter from '@/utils/mitt'
  4. let tsMQ : TsMQ = TsMQ.getInstance();
  5. //投送消息
  6. function pushMQs() {
  7. console.log(`M2投递时间:${new Date().toLocaleString()}`)
  8. tsMQ.pushMessage("HelloWord",1000 * 20,{ name : 'M2', second:20 });
  9. tsMQ.pushMessage("HelloWord",1000 * 3,{ name : 'M1', second:3 });
  10. }
  11. </script>
  12. <template>
  13. <div id="app" style="display: flex;flex-direction: column;justify-content: center;height: 100%;width: 100%;margin: 0;padding: 0">
  14. <span @click="pushMQs">MQ投送</span>
  15. </div>
  16. </template>

提示:这里采用事件模拟投送消息 

 消息订阅代码:
  1. <script setup lang="ts">
  2. import TsMQ from '@/utils/TsMQ'
  3. import emitter from '@/utils/mitt'
  4. let tsMQ : TsMQ = TsMQ.getInstance();
  5. //订阅消息
  6. emitter.on("HelloWord",e => {
  7. console.log(`收到消息:${JSON.stringify(e)}\n消息时间:${new Date().toLocaleString()}`)
  8. });
  9. function takeMQs() {
  10. console.log(tsMQ.takeMessage('HelloWord'));
  11. }
  12. </script>
  13. <template>
  14. <div id="app" style="display: flex;flex-direction: column;justify-content: center;height: 100%;width: 100%;margin: 0;padding: 0">
  15. <span @click="takeMQs">MQ获取</span>
  16. </div>
  17. </template>

效果:

总结:我们可以看到我们实现了这个功能 ,其中可以用来作为缓存使用,同理可写

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号