Skip to content

弹幕冷却时间

描述

在直播的场景中,当用户在短时间内高频率的发送弹幕时,会有刷屏的嫌疑,本章节会对这种场景给出一个简单的实现,你可以参考其原理和思想自行根据你的业务场景进行扩展。

提示

我们主要依赖 willRender 这个钩子来实现。

根据弹幕内容来实现

ts
import { create } from 'danmu';

const cd = 3000;
const map = Object.create(null);

// 创建 manager,定义发送弹幕的类型为 string
const manager = create<string>({ ... });

// 写一个插件来专门处理弹幕 cd 的事情
manager.use({
  name: 'cd',
  willRender(ref) {
    const now = Date.now();
    const content = ref.danmaku.data;
    const prevTime = map[content];

    if (prevTime && now - prevTime < cd) {
      ref.prevent = true;
      console.warn(`"${content}" is blocked.`);
    } else {
      map[content] = now;
    }
    return ref;
  },
});

// ✔️ 成功
manager.push('弹幕内容'); 

// ❌ 被阻止
manager.push('弹幕内容'); 

// ✔️ 成功
setTimeout(() => {
  manager.push('弹幕内容'); 
}, 3000)

根据用户 ID 来实现

ts
import { create } from 'danmu';

// 创建 manager,定义发送弹幕的类型为 { userId: number, content: string }
const manager = create<{ userId: number, content: string }>({ ... });

const cd = 3000;
const map = Object.create(null);

manager.use({
  name: 'cd',
  willRender(ref) {
    const now = Date.now();
    const { userId } = ref.danmaku.data;
    const prevTime = map[userId];

    if (prevTime && now - prevTime < cd) {
      ref.prevent = true;
      console.warn(`"${userId}" is blocked.`);
    } else {
      map[userId] = now;
    }
    return ref;
  },
});

// ✔️ 成功
manager.push({ useId: 1, content: 'content1' }); 

// ❌ 被阻止
manager.push({ useId: 1, content: 'content2' }); 

// ✔️ 成功
setTimeout(() => {
  manager.push({ useId: 1, content: 'content3' }); 
}, 3000)

Released under the MIT License.