实现js熔断机制

写在前言

这是以前看到的一道面试题:javascript

如何实现一个能强制中断死循环的方法?java

想了下仍是挺有意思,咱们都知道,死循环能够经过break打断:面试

var idx=0;
while(1){
    idx++;
    if(idx>10){
        break; // 打断退出循环
    }
}

复制代码

实现:

可是若是想封装成一个函数,我是没有找到好的方法,可是咱们能够使用另一个方案,就是throw new Error() ,抛出异常,咱们能够经过闭包来存储执行函数的次数,规定若是超过多少次则认定为死循环,抛出异常:闭包

function fusing(){
    let idx = 0;
    return function(){
        idx++;
        if(idx>1000){
            idx=0;
            throw new Error('强制熔断');
        }
    }
}

复制代码

来尝试下,跑一个死循环:app

let fus = fusing();
while(1){
    fus(); //Uncaught Error: 强制熔断
}

复制代码

可以正常工做,固然咱们能够继续完善这个函数,改为使用时间戳和计数配合的方式,好比:函数

function fusing(options={times:100,timer:10000}){
    let {times,timer} = options;
    let idx = 0;
    let start = new Date().getTime(); // 获取当前时间戳
    return function(){
        idx++;
        let end = new Date().getTime(); //获取执行时间
        if(idx>times||end-start >= timer){ //10秒后执行或者idx大于100次执行
            idx=0;
            start = null;
            throw new Error('强制熔断');
        }
    }
}    

复制代码

或者把它丢到方法的原型对象里面测试

Function.prototype.fusing = function (options = { times: 100, timer: 10000 }) {
  let { times, timer } = options;
  let idx = 0;
  let start = new Date().getTime(); // 获取当前时间戳
  const thisArgs = this
  return function () {
    thisArgs.apply(null, arguments);
    idx++;
    let end = new Date().getTime(); //获取执行时间
    if (idx>=times||end - start >= timer) { //10秒后执行或者idx大于100次执行
      idx = 0;
      start = null;
      throw new Error('强制熔断');
    }
  }
}  
复制代码

调用的时候就能够自行使用函数ui

function say(w){
    console.log(w);
}
var s = say.fusing();
while(1){
    s('测试');
}

复制代码

写在最后

其实,我能想到的在现实业务中的使用场景,也只有为了防止某些可能存在死循环或者在防止某些调用次数过多的函数致使页面爆栈的状况下使用,不过也能够做为一个扩充了解,万一面试中问到呢?this

相关文章
相关标签/搜索