请问js代码,怎么在一定时间内只执行一次

CaixK
  • 343

请问js代码,怎么在一定时间内只执行一次

  response => {
  ...
  ...
  },
  error => {
    if (error.response.status == '401') { 
      store.dispatch('user/resetToken').then(() => {
        router.push('/login?redirect=' + router.history.current.fullPath)
      })
    }
    Message({   //这里失效状态下,调用多个接口会执行多此
      // message: error.message,
      message: '登录信息失效,请重新登录',
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)
回复
阅读 676
8 个回答

就是一个节流函数
lodash工具库里面有一个 throttle方法

func (Function): 要节流的函数。
[wait=0] (number): 需要节流的毫秒。
[options={}] (Object): 选项对象。
[options.leading=true] (boolean): 指定调用在节流开始前。
[options.trailing=true] (boolean): 指定调用在节流结束后。
   //全局变量
   let enable = true
  if (error.response.status == '401') { 
      store.dispatch('user/resetToken').then(() => {
        router.push('/login?redirect=' + router.history.current.fullPath)
      })
    }
    if(enable) {
      Message({   //这里失效状态下,调用多个接口会执行多此
      // message: error.message,
      message: '登录信息失效,请重新登录',
      type: 'error',
      duration: 5 * 1000
     })
     enable = false
     setTimeout(() => {
       enable = true
     }, 3 * 1000)
    }
    
    return Promise.reject(error)

结合一楼的回答 补充一下

const _error = _.throttle(error => {
    if (error.response.status == '401') { 
      store.dispatch('user/resetToken').then(() => {
        router.push('/login?redirect=' + router.history.current.fullPath)
      })
    }
    Message({   //这里失效状态下,调用多个接口会执行多此
      // message: error.message,
      message: '登录信息失效,请重新登录',
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
},5000);
response => {
  ...
  ...
  },
  _error
)

类似的,可以本地设置一个循环计数器,在计数器重置时重置一个标记变量,执行函数前检查标记变量状态,如果已经置位则不执行,否则执行,并置位标记变量。

已参与了 SegmentFault 思否「问答」打卡,欢迎正在阅读的你也加入。
var MessageWithThrottle = throttle(Message)
response => {
...
...
},
error => {
  if (error.response.status == '401') { 
    store.dispatch('user/resetToken').then(() => {
      router.push('/login?redirect=' + router.history.current.fullPath)
    })
  }
  MessageWithThrottle({   //这里失效状态下,调用多个接口会执行多此
    // message: error.message,
    message: '登录信息失效,请重新登录',
    type: 'error',
    duration: 5 * 1000
  })
  return Promise.reject(error)
}
)

/**
 * 节流
 * @param {(arg: *) => *} fn 
 * @param {number} [delay=300] 时间间隔ms
 */
function throttle(fn, delay=300) {
let prev = 0;
return function throttled(...args) {
  if(Date.now() - prev >= delay) {
    prev = Date.now();
    fn.apply(this, args);
  }
}
}
已参与了 SegmentFault 思否「问答」打卡,欢迎正在阅读的你也加入。
小脏孩
  • 2
新手上路,请多包涵
class Notify {
    message = [];
    Executing = {};
    timer = null;
    timeOut = null;
    // 添加消息进来
    addMessage(option) {
        this.message.push(option);
        clearTimeout(this.timeOut);
        this.timeOut = setTimeout(() => {
            this.server();
        }, 100);
    }
    // 消息服务
    server() {
        clearInterval(this.timer);
        this.getMessage();
        // console.log(this.checkMessage());
        this.timer = setInterval(() => {
            console.log(this.message);
            try {
                this.getMessage();
            } catch (err) {
                clearInterval(this.timer);
                this.timer = null;
            }
            if (this.message.length <= 0) {
                clearInterval(this.timer);
                this.timer = null;
            }
        }, 100);
    }
    getMessage() {
        let msg = this.message[0];
        this.message.shift();
        this.pushMessage(msg);
    }

    // 推送逻辑  判断类型
    pushMessage(msg) {
        let that = this;
        // if (!msg.toString) {
        //     console.log('消息类型错误');
        // }
        if (!msg || msg.toString() != '[object Object]') {
            throw new Error('消息类型错误');
        }
        if (!(msg.flag in this.Executing)) {
            // console.log('处理消息:', msg);
            let flag = msg.flag || new Date() * 1;
            this.Executing[flag] = 'OnShow';
            if (msg.fn instanceof Function) {
                msg.fn(() => {
                    delete this.Executing[flag];
                    // console.log('end clear 显示列表', this.Executing);
                });
            } else {
                console.error('没有回调方法');
            }
        }
    }
}

export default Notify;

导出实例,我是这么简单用的,有需要的话可以结合一下单例模式

import Notify from './notify.js';
export default new Notify();

调用

Notify.addMessage({
        fn: (callback) => {
           //do something...
           callback();//执行完毕之后通知清除这个事件
        },
        flag: "loginModal",
    });

代码有点丑,思路就是这样的

没有用节流的原因是,需要立即触发,且有一个任务执行中时不会再触发第二次,任务结束之后才能再次触发

节流就可以啦

const throttle = (fn, delay = 500) => {
  let timer = null;
  var _this = this;

  return function() {
      var args = Array.prototype.slice.call(arguments);
      if(!timer){
          timer = setTimeout(() => {
              fn.apply(_this, args);
              timer = null;
          }, delay)
      }
  }
}

最外层引入,包裹Message就可以了

已参与了 SegmengtFault 思否 「问答」打卡,欢迎正在阅读的你也加入。

感觉你解决思路的方向有点 偏啊,你这个问题 解决方案并不是 节流,而是 需要权限控制。
简单说就是 那些 接口失败了,需要弹出“无权限的message”。往大了讲,就是 什么时候启用 公共的 Message弹框,什么时候启用特定的Message弹框。

你这个问题 最简单的解决方案就是 设定一个 白名单列表,比如 whiteList = ["/getUserInfo"],如果这个接口需要登录权限认证,而又是第一个发起的请求,那么 验证一下 request.url 是不是在白名单内,是的话,弹出Message

仅供参考,谢谢!

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏