Js常用方法(持续更新ing)

256 阅读3分钟

18.给 fetch 添加超时功能

AbortController是一个控制器对象(DOM API),可通过new '构造函数'的方式生成控制器实例对象,可通过该控制器实例对象根据需要终止/取消一个或多个Web请求/监听事件

通过new生成的控制器实例对象很干净,身上只有一个 abort() 方法,和一个 signal(AbortSignal对象)属性,signal 属性上还有 aborted、onabort、reason 三个属性,我们主要使用 aborted 属性,表示是否已终止,其初始值为false。

参考:# 认识 AbortController控制器对象 及其应用

function createRequestTimeout(timeout = 3000) {
    return function (url, options) {
        return new Promise((resolve, reject) => {
            const controller = new AbortController();
            options = options || {};
            if(options.signal){
                options.signal.addEventLister('abort',()=>{
                 controller.abort();
                 },{once:true})
             }
            options.signal = abort.signal;
            setTimeout(() => {
                reject(new Error("Request timeout"));
                controller.abort();
            }, timeout);
            fetch(url, options).then(resolve, reject);
        });
    };
}

17.并发任务控制

请实现 SuperTask 函数实现多任务的并发请求控制

function timeout(time){
    return new Promise((resolve)=>{
        setTimeout(()=>{
            resolve();
        },time)
    })
}

const superTask= new SuperTask();

function addTask(time,name){
    superTask
        .add(()=>timeout(time))
        .then(()=>{
        console.log(`任务${name}完成`);
    })
}

addTask(10000,1);// 10000ms后输出:任务1完成
addTask(5000,2);// 5000ms后输出:任务2完成
addTask(3000,3);// 8000ms后输出:任务3完成
addTask(4000,4);// 12000ms后输出:任务4完成
addTask(5000,5);// 15000ms后输出:任务5完成
class SuperTask {
    constructor(parallelcount = 2) {
        this.parallelcount = parallelcount; // 并发数
        this.runningCount = 0; // 正在运行的数量
        this.tasks = []; // 任务列表
    }

    add(task) {
        return new Promise((resolve, reject) => {
            this.tasks.push({
                task,
                resolve,
                reject,
                });
            this._run();
        });
    }

    // 依次运行tasks队列里所有的任务
    _run() {
        while (this.runningCount < this.parallelcount && this.tasks.length) {
            const { task, resolve, reject } = this.tasks.shift();
            this.runningCount++;
            task()
                .then(resolve, reject)
                .finally(() => {
                this.runningCount--;
                this._run();
            });
        }
    }
}

16.NodeJS全局替换生成新文件

该方法主要是现有工作中调角标所用,不具有普遍性。
var fs =require("fs");
var filePath ="./text.html";
try {
    fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
        throw err;
    }
    const replacements = [
        {
            pattern: /footnote-(\d{1,2})/g,
            replace: (match, group) => {
                const number = parseInt(group);
                    return (number >= 4) ? `footnote-${number - 1}` : match;
            }
        },
        {

            pattern: /脚注\s(\d{1,2})/g,
            replace: (match, group) => {
                const number = parseInt(group);
                    return (number >= 4) ? `脚注 ${number - 1}` : match;
                }
        },
        {
            pattern: /data-modal-close>(\d{1,2})/g,
            replace: (match, group) => {
                const number = parseInt(group);
                    return (number >= 4) ? `data-modal-close>${number - 1}` : match;
            }

        }];

        replacements.forEach(({ pattern, replace }) => {
            data = data.replace(pattern, replace);
        });
        fs.writeFileSync('text.html', data, 'utf8');
        console.log('文件已被覆盖');

    });
} catch (err) {
    throw err;
 }
});

15.参数反序列化

/**
* 要求给你一个 url,需要得到这个链接里所有的参数对象
* @param {url} url
* @returns 参数对象
*/
function deserialize(url){
    return Object.fromEntries(new Url(url).searchParams)
}

let str = "https://www.baidu.com/baidu.php?url=0s0000aPch_Smgbn9yquo6aar8a2ZFM9VU2Vr9Qy0eXL8amfJ5Pl7F6FumUDW9lYFBczA96E6-QoT3ruya79l5aJL8BaDtqaA1yix0keu8-ydLQmzDX0E1AQU5hiSUtY2ARzVurOosVwKMwMchBOGNoH4_ct3mZBqxj_EAnkeh0mUSzdPZMp_oxVoZAtK7FeVFgs1xQb0YAYwtggSRfbt71FOidv.DY_NR2Ar5Od66lISOAS7DZXPr-BEoAMHzq8FWGtIMugudWHG4pAWA-BVi_nYQA1ker26.U1Yk0ZDq1U1AojcsnWHfs_vtkJs0TA-W5H00TZPGuv3qPADvujnznAn1njn3nHR4PhfzPHD3mH7hPvw9PWc4mhR0IjLPEQOBFHcszqBzkQOB0A-V5HczPfKM5yq-TZns0ZNG5yF9pywd0ZKGujYz0APGujYYnj00UgfqnH0krNtknjDLg1csPH7xn1DzP7tznjmzg1nvnjD0pvbqn0KzIjYYnHf0mhbqnHR3g1csP7tdnjn0UynqnH0krNtknjDLg1csPH7xnH0zg1cvPHRkrjnsrH6Lg100TgKGujYs0Z7Wpyfqn0KzuLw9u1Ys0A7B5HKxn0K-ThTqn0KsTjYs0A4vTjYsQW0snj0snj0s0AdYTjYs0AwbUL0qnfKzpWYs0Aw-IWdsmsKhIjYs0ZKC5H00ULnqn0KBI1YknfK8IjYs0ZPl5fK9TdqGuAnqTZnVuLG8TsKGuAnqiD4a0ZKCIZbq0Zw9ThI-IjY1nNt1nHFxnH0sPfKYIgnqrH63rjDvPjcdnj61nj63PW61P6Kzug7Y5HDLnH0Ynj0LnjD3rjm0Tv-b5H9-uHIhn1Rsnj0kuAnYP1m0mLPV5RwAwRDdnjnsPbfvP1R1wj60mynqnfKsUWYs0Z7VIjYs0Z7VT1Ys0ZGY5H00UyPxuMFEUHYsg1Kxn7tsg1Kxn0Kbmy4dmhNxTAk9Uh-bT1Ysg1Kxn7tYP1b1rjfLg1Kxn0Ksmgwxuhk9u1Ys0AwWpyfqn0K-IA-b5iYk0A71TAPW5H00IgKGUhPW5H00Tydh5H00uhPdIjYs0A-1mvsqn0K9uAu_myTqnfK_uhnqn0KbmvPb5fKYTh7buHYLP10drHb0mhwGujY4rjf4nbcknDDvrRcLwHw7wWKafW77rHFaPRcznWPar0KEm1Yk0AFY5H00Uv7YI1Ys0AqY5H00ULFsIjYsc10Wc10Wnansc108nj0snj0sc10WwDuRc10WQinsQW0snj0snankQW0snj0snansc10Wna3snj0snj0Wnansc10Wnans0AF9UhV9mvnqnansc10Wn0K3TLwd5HcsnHcYnHTd0Z7xIWYsQWD1g108njKxna3sn7tsQWD1g108njKxn7tsQW0sg100mMPxTZFEuA-b5H00ThqGuhk9u1Ys0APv5fKGTdqWTADqn0KWTjYs0AN1IjYs0Z7MIvfqn0KWThnqnHckn1b&us=newvui&xst=mWY4rjf4nbcknDDvrRcLwHw7wWKafW77rHFaPRcznWPar0715HDsnWbLPjmvPHbLrHnsrjDzPHnYg1czPNts0gTq1UzO3BjQvQQDEScKTHLPEnp_nW0zPPja1U1Ao07d5HcsnHcYnHTd0gfqnHTknjfsnjTsn67VTHYs0W0aQf7Wpjdhmdqsms7_IHYs0yP85yF9pywd0gFY5H0KnHT1Pj6dnWDd&word=&ck=6958.19.72.307.196.233.189.182&shh=www.baidu.com&sht=baidu&wd=&bc=110101";


console.log(deserialize(str))
/** result
{
    url: '0s0000aPch_Smgbn9yquo6aar8a2ZFM9VU2Vr9Qy0eXL8amfJ5Pl7F6FumUDW9lYFBczA96E6-QoT3ruya79l5aJL8BaDtqaA1yix0keu8-ydLQmzDX0E1AQU5hiSUtY2ARzVurOosVwKMwMchBOGNoH4_ct3mZBqxj_EAnkeh0mUSzdPZMp_oxVoZAtK7FeVFgs1xQb0YAYwtggSRfbt71FOidv.DY_NR2Ar5Od66lISOAS7DZXPr-BEoAMHzq8FWGtIMugudWHG4pAWA-BVi_nYQA1ker26.U1Yk0ZDq1U1AojcsnWHfs_vtkJs0TA-W5H00TZPGuv3qPADvujnznAn1njn3nHR4PhfzPHD3mH7hPvw9PWc4mhR0IjLPEQOBFHcszqBzkQOB0A-V5HczPfKM5yq-TZns0ZNG5yF9pywd0ZKGujYz0APGujYYnj00UgfqnH0krNtknjDLg1csPH7xn1DzP7tznjmzg1nvnjD0pvbqn0KzIjYYnHf0mhbqnHR3g1csP7tdnjn0UynqnH0krNtknjDLg1csPH7xnH0zg1cvPHRkrjnsrH6Lg100TgKGujYs0Z7Wpyfqn0KzuLw9u1Ys0A7B5HKxn0K-ThTqn0KsTjYs0A4vTjYsQW0snj0snj0s0AdYTjYs0AwbUL0qnfKzpWYs0Aw-IWdsmsKhIjYs0ZKC5H00ULnqn0KBI1YknfK8IjYs0ZPl5fK9TdqGuAnqTZnVuLG8TsKGuAnqiD4a0ZKCIZbq0Zw9ThI-IjY1nNt1nHFxnH0sPfKYIgnqrH63rjDvPjcdnj61nj63PW61P6Kzug7Y5HDLnH0Ynj0LnjD3rjm0Tv-b5H9-uHIhn1Rsnj0kuAnYP1m0mLPV5RwAwRDdnjnsPbfvP1R1wj60mynqnfKsUWYs0Z7VIjYs0Z7VT1Ys0ZGY5H00UyPxuMFEUHYsg1Kxn7tsg1Kxn0Kbmy4dmhNxTAk9Uh-bT1Ysg1Kxn7tYP1b1rjfLg1Kxn0Ksmgwxuhk9u1Ys0AwWpyfqn0K-IA-b5iYk0A71TAPW5H00IgKGUhPW5H00Tydh5H00uhPdIjYs0A-1mvsqn0K9uAu_myTqnfK_uhnqn0KbmvPb5fKYTh7buHYLP10drHb0mhwGujY4rjf4nbcknDDvrRcLwHw7wWKafW77rHFaPRcznWPar0KEm1Yk0AFY5H00Uv7YI1Ys0AqY5H00ULFsIjYsc10Wc10Wnansc108nj0snj0sc10WwDuRc10WQinsQW0snj0snankQW0snj0snansc10Wna3snj0snj0Wnansc10Wnans0AF9UhV9mvnqnansc10Wn0K3TLwd5HcsnHcYnHTd0Z7xIWYsQWD1g108njKxna3sn7tsQWD1g108njKxn7tsQW0sg100mMPxTZFEuA-b5H00ThqGuhk9u1Ys0APv5fKGTdqWTADqn0KWTjYs0AN1IjYs0Z7MIvfqn0KWThnqnHckn1b',
    us: 'newvui',
    xst: 'mWY4rjf4nbcknDDvrRcLwHw7wWKafW77rHFaPRcznWPar0715HDsnWbLPjmvPHbLrHnsrjDzPHnYg1czPNts0gTq1UzO3BjQvQQDEScKTHLPEnp_nW0zPPja1U1Ao07d5HcsnHcYnHTd0gfqnHTknjfsnjTsn67VTHYs0W0aQf7Wpjdhmdqsms7_IHYs0yP85yF9pywd0gFY5H0KnHT1Pj6dnWDd',
    word: '',
    ck: '6958.19.72.307.196.233.189.182',
    shh: 'www.baidu.com',
    sht: 'baidu',
    wd: '',
    bc: '110101'
}
*/

14.数组对象去重

/**
 * 数组对象去重
 * @param {Array} arr 
 * @param {String} key 
 * @returns Array
 */

function deWeight(arr = [], key) {
  const tempObj = {};
  const result = arr.reduce((prev, now) => {
    tempObj[now[key]] ? "" : (tempObj[now[key]] = true && prev.push(now));
    return prev;
  }, []);
  return result;
}

13.将传入的函数放到微队列中执行

MutationObserver:一个浏览器环境中JavaScript API,可以用于监听 DOM 树中指定节点及其子节点的变化,当节点内容、属性、子节点结构等发生改变时,它可以及时检测到并触发回调函数。 MutationObserver的config参数可以用来指定监听的类型,它有以下几个属性: attributes:监听属性变化; childList:监听子节点的添加、删除; characterData:监听文本内容的变化; subtree:监听目标节点的所有后代节点的变化

/**
* 将传入的函数放到微队列中执行
* 参照Vue源码
* @param {Function} func

function runMicroTask(func) {
    if(typeof Promise === 'function'){
        Promise.resolve().then(func);
        return;
    }
    
    if(typeof MutationObserver === 'function'){
        var ob = new MutationObserver(func);
        var node = document.createTextNode('');
        ob.observe(node,{characterData:true})
        node.data = 1;
        return;
    }

    // 兼容node环境(高)
    if(process && process.nextTick === 'function'){
        process.nextTick(func);
        return;
    }

    // 兼容node环境(低)
    if(typeof setImmediate ==='function'){
        setImmediate(func);
        return;
    }
    setTimeout(func);
}

12.将一维数组按要求转成二维数组

/**
* 将一维数组转成二维数组
* @param {Array} arr
* @param {Number} num
* @returns {Array} 二维数组
*/

function ArrayTwo(arr=[],num){
    let _arr = [];
    for(let i=0;i<arr.length;i+=num){
        _arr.push(arr.slice(i,i+num))
    }
    return _arr;
}

11.使用正则前瞻检查密码强度

/**
* 使用正则前瞻检查密码强度
* 要求:1、password必须6-12位;2、必须包含数字、小写字母、大写字母、特殊字符($@,_.)
* 正则匹配时,会依次向后移动(消耗字符),导致顺序问题
* 前瞻运算符:(?=规则) 不消耗字符
* .* 任意字符出现零到多次
* @param str {String} 待验证的密码
* @returns {Boolean} 验证密码强度是否符合要求
*/

function validatePwd(str){
    const regex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[$@,_.])[\da-zA-Z$@,_.]{6,12}$/
    return regex.test(str);
}

10. 随机生成多位字符串

/**
* 生成随机多位字符串
* @param len {Number} 随机字符串长度
* @returns {String}
*/

function randomString(len=6) {
    if (len <= 11) {
        return Math.random()
        .toString(36)
        .slice(2, 2 + len)
        .padEnd(len, "0");
    } else {
        // 递归
        return randomString(11) + randomString(len - 11);
    }

}

9.随机生成16进制颜色

/**
* 生成16进制随机颜色
* @returns {String} 颜色
*/

function randomColor() {
    return `#${Math.random().toString(16).slice(2, 8)}`;
}

8.将光标放在最后一位

/**
* @param ctrl {Object} dom节点
* @param pos {Number} 字符位置的下标
*/

const setCursorPosition = (ctrl, pos) => {
  // ctrl:dom;pos:string length
  ctrl.focus();
  ctrl.setSelectionRange(pos, pos);
};

7.Cookie二次封装

const Cookie = {
  //存储
  set(key, value) {
    const expires = new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000); // 7天
    cookie.save(key, value, { path: "/", expires });
  },
  
  //取出数据
  get(key) {
    return cookie.load(key);
  },
  
  // 删除数据
  remove(key) {
    cookie.remove(key);
  },

  clear() {
    const keys = document.cookie.match(/[^ =;]+(?=\=)/g);
    if (keys) {
      for (let i = keys.length; i--; ) {
        document.cookie =
          keys[i] + "=0;path=/;expires=" + new Date(0).toUTCString(); //清除当前域名下的,例如:m.kevis.com
        document.cookie =
          keys[i] +
          "=0;path=/;domain=" +
          document.domain +
          ";expires=" +
          new Date(0).toUTCString(); //清除当前域名下的,例如 .m.kevis.com
        document.cookie =
          keys[i] +
          "=0;path=/;domain=kevis.com;expires=" +
          new Date(0).toUTCString(); //清除一级域名下的或指定的,例如 .kevis.com
      }
    }
  },
};

6.localStorage/sessionStorage 二次封装

const Storage = {
  //存储
  set(key, value) {
    localStorage.setItem(key, JSON.stringify(value));
  }, 
  
  //取出数据
  get(key) {
    try {
      const value = localStorage.getItem(key);
      if (value === null || value === undefined || value === "") {
        return null;
      }
      return JSON.parse(localStorage.getItem(key));
    } catch (err) {
      return null;
    }
  }, 
  
  // 删除数据
  remove(key) {
    localStorage.removeItem(key);
  },

  clear() {
    localStorage.clear();
  },
};

5.正则验证URL

const vertifyLink = (url) => {
  const strReg = /(http|https):\/\/([\w.]+\/?)\S*/;
  
  const reg = new RegExp(strReg);
  
  if (reg.test(url)) {
    return true;
  } else {
    return false;
  }
}

4.识别字符串里的url

const translateHtml = (msg) => {
  const reg =
    /((http|https):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|])/g;
    
  const textR = msg.replace(
    reg,
    "<a href='$1' target='_blank' style='text-decoration: underline;color:#ffffff'>$1</a>"
  );
  
  return textR;
}

3.下载功能

const downloadBlob = (blob, fileName) => {
  const oblob = new Blob([blob]);
  if (typeof window.navigator.msSaveBlob !== "undefined") {
    window.navigator.msSaveBlob(blob, fileName);
  } else {
    const URL = window.URL || window.webkitURL;
    const objectUrl = URL.createObjectURL(oblob);
    if (fileName) {
      const a = document.createElement("a");
      if (typeof a.download === "undefined") {
        window.location = objectUrl;
      } else {
        a.href = objectUrl;
        a.download = fileName;
        document.body.appendChild(a);
        a.click();
        a.remove();
      }
    } else {
      window.location = objectUrl;
    }
  }
}

配合axios封装使用

if (res && response.headers["content-disposition"]) {
  const filename =
    response.headers["content-disposition"]?.split("filename=")[1];
  return {
    filename,
    blob: res
  };
}

2.时间格式化

// 补零操作
function zeroize(num) {
  return num < 10 ? "0" + num : num;
}

const formatTime = (time) => {
  if (!time) return;
  const t = new Date(time * 1000);
  // 年
  const oldY = t.getFullYear();
  // 月
  const oldM = t.getMonth() + 1;
  // 日
  const oldD = t.getDate();
  // 时
  const oldH = t.getHours();
  // 分
  const oldi = t.getMinutes();
  // 秒
  const olds = t.getSeconds();
  
  return `${oldY}-${zeroize(oldM)}-${zeroize(oldD)} ${zeroize(oldH)}:${zeroize(
    oldi
  )}:${zeroize(olds)}`;
};

1.解析Url

const getParams = URL => JSON.parse(`{"${decodeURI(URL.split("?")[1]).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`) 
getParams("https://www.google.com.hk/search?q=js+md&newwindow=1");
// {q: 'js+md', newwindow: '1'}