js 有没有队列执行这种东西?

作者站长头像
站长
· 阅读数 5

我有个js写的函数如下:

function myAlert(str, config) {
    if ($('#alertBox').length) {
        $('#alertBox').remove();
    }
    var defaultConfig = {
        millisecond: 3000
    };
    config = Object.assign(defaultConfig, config);
    str = '<div id="alertBox">' + str + '</div>';
    $('body').append(str);
    $('#alertBox').css({
        'top': parseFloat((($(window).height()) / 2 + window.scrollY) * 9 / 10) + 'px',
        'left': Math.floor(($(window).width() - $('#alertBox').outerWidth(true)) / 2) + 'px',
        'zIndex': typeof config.zIndex == 'undefined' ? '' : config.zIndex
    }).fadeIn('fast').delay(parseInt(config.millisecond)).fadeOut('fast', function () {
        this.remove();
    });
}

这个函数是用来做提醒的,调用一次页面弹出一个提醒框,显示 3 秒然后自动关掉,现在有个问题,如果我有两次调用,并且调用间隔很小的话,那么第一次的弹框内容还没有显示够 3 秒的时间就直接显示了第二次的弹窗内容给取代了,我尝试了很久不知道怎么解决这个问题,希望有个前端大佬帮忙看看,谢谢。

我的期望是即使我调用 n 次,他每次都要显示我定义的那个 millisecond 时间之后关闭,间隔 300 毫秒后,再继续显示下一个,直到 n 次显示完再关闭。

经大佬指点,我自己总结成了一个方法写到了下面,基本达到目的了,再次谢谢各位回答的大佬!

function oppoMsg(str, config) {
    if ($('#alertBox').length) {
        $('#alertBox').remove();
    }
    str = '<div id="alertBox">' + str + '</div>';
    $('body').append(str);
    $('#alertBox').css({
        'top': parseFloat((($(window).height()) / 2 + window.scrollY) * 9 / 10) + 'px',
        'left': Math.floor(($(window).width() - $('#alertBox').outerWidth(true)) / 2) + 'px',
        'zIndex': typeof config.zIndex == 'undefined' ? '' : config.zIndex
    }).fadeIn('fast').delay(parseInt(config.millisecond)).fadeOut('fast', function () {
        this.remove();
    });
}
function queueFn(fn) {
    const queue = [];
    let running = false;

    function next() {
        if (running) return;
        if (!queue.length) return;
        running = true;
        var args = queue.pop(), config = {millisecond: 3000};//这里做了一些改动
        config = Object.assign(config, args[0][1]);
        try {
            fn.call(this, args[0][0], config);
        } catch (err) {
            console.error(err)
        }
        setTimeout(function () {
            running = false;
            setTimeout(function () {
                next();
            }, 200);//这里又加了一个定时器,先消失再弹出来
        }, config.millisecond);
    }

    return function (...args) {
        queue.push([args, this]);
        next();
    }
}

const queuedOppoMsg = queueFn(oppoMsg);

function myAlert(str, type, config, idName, reportError) {
    type = type || 'alert';
    idName = idName || 'showApiAlert';
    reportError = reportError || false;
    if (reportError) {
    }
    switch (type) {
        case 'alert':
            alert(str);
            break;
        case 'msg':
            //TO DO 要解决这个提醒会被覆盖的问题
            queuedOppoMsg(str, config);
            break;
        case 'notice':
            break;
}

测试代码:

for (var i = 0; i < 2; i++) {
    myAlert('test' + i, 'msg');
}
回复
1个回答
avatar
test
2024-06-25
function queueFn(fn){
  const queue = [];
  let running = false;
  function next(){
    if(running) return;
    if(!queue.length) return;
    running = true;
    const [[str, {zIndex = "", millisecond = 3000}], context] = queue.pop();

    try{
      fn.call(this, str, {zIndex, millisecond});
    } catch(err){console.error(err)}
    
    setTimeout(function(){
      running = false;
      next();
    }, millisecond);
  }
  return function(...args){
    queue.push([args, this]);
    next();
  }
}
const queuedMyAlert = queueFn(myAlert);

原来调用 myAlert 的地方,改为调用 queuedAlert 即可。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容