基于随机时间间隔实现JavaScript通知错开显示并设置触发次数
实现FOMO社交证明通知的触发问题
我想要在页面上实现一种“FOMO/社交证明”效果,让通知滑入后再滑出。要求通知触发5次后停止,且每次触发间隔随机时长。
但目前用setTimeout实现时,所有通知无间隔连续触发,控制台显示时长值不同,但都是初始设置的,导致通知堆叠而非错开显示。
期望的流程:
- 5秒后→通知滑入,等待7秒后滑出,间隔随机时长
- 重复上述动作,总共触发5次后停止
原代码如下:
$(function() { var counterVal = 0; doFomoSequence(counterVal); function doFomoSequence(counterVal){ var secVal = Math.floor(Math.random() * 10000); //secVal = 3000; setTimeout(doFomo(secVal), 5000); counterVal++; if(counterVal <= 5){ doFomoSequence(counterVal); } } function doFomo(secVal){ console.log(secVal); setTimeout( slideIn, secVal ); setTimeout( slideOut, secVal + 7000 ); } function slideIn(){ $('#notification').animate({left: 20}, 'slow'); } function slideOut(){ $('#notification').animate({left: -400}, 'slow'); } });
问题分析与解决方案
核心问题
setTimeout调用错误:setTimeout(doFomo(secVal), 5000)里直接执行了doFomo(secVal),而非传递函数引用,导致所有doFomo立即执行,通知直接堆叠。- 递归时机错误:原代码一次性递归调用5次
doFomoSequence,没有等待前一次通知的完整周期结束,导致所有通知的定时器同时启动。
修正后的代码
$(function() { var counterVal = 0; // 初始等待5秒后启动第一次通知 setTimeout(startFomoSequence, 5000); function startFomoSequence() { if (counterVal >= 5) return; // 达到5次直接停止 // 生成0-10秒的随机间隔时长 var randomDelay = Math.floor(Math.random() * 10000); // 执行本次通知的滑入+滑出逻辑 slideIn(); setTimeout(slideOut, 7000); // 通知显示7秒后滑出 // 等待滑出动画完成 + 随机间隔后,启动下一次通知 setTimeout(function() { counterVal++; startFomoSequence(); }, 7000 + randomDelay + 600); // +600是补偿slideOut的slow动画时长(默认600ms) } function slideIn(){ $('#notification').animate({left: 20}, 'slow'); } function slideOut(){ $('#notification').animate({left: -400}, 'slow'); } });
关键改动说明
- 改成链式调度逻辑:只有当前一次通知的滑出动画完全结束,再加上随机间隔后,才触发下一次通知,彻底避免堆叠。
- 修正
setTimeout调用方式:传递函数引用而非立即执行函数,保证定时器按预期延迟触发。 - 增加动画时长补偿:给
slideOut的动画留足执行时间,确保通知完全滑出后再开始下一轮流程。
内容的提问来源于stack exchange,提问作者hanji
相关产品推荐
相关产品推荐

