實現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

相關文章
相關標籤/搜索