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'}