节流
function debounce(fn, delay) {
let timer
return function (...args) {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
// 测试
const task = () => {
console.log('run task')
}
const debounceTask = debounce(task, 1000)
window.addEventListener('scroll', debounceTask)
防抖
function throttle(fn, delay) {
let last = 0 // 上次触发工夫
return (...args) => {
const now = Date.now()
if (now - last > delay) {
last = now
fn.apply(this, args)
}
}
}
// 测试
const task = () => {
console.log('run task')
}
const throttleTask = throttle(task, 1000)
window.addEventListener('scroll', throttleTask)
深拷贝
function deepClone(obj, cache = new WeakMap()) {
if (typeof obj !== 'object') return obj // 一般类型,间接返回
if (obj === null) return obj
if (cache.get(obj)) return cache.get(obj) // 避免循环援用,程序进入死循环
if (obj instanceof Date) return new Date(obj)
if (obj instanceof RegExp) return new RegExp(obj)
// 找到所属原型上的constructor,所属原型上的constructor指向以后对象的构造函数
let cloneObj = new obj.constructor()
cache.set(obj, cloneObj) // 缓存拷贝的对象,用于解决循环援用的状况
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝
}
}
return cloneObj
}
// 测试
const obj = { name: 'Jack', address: { x: 100, y: 200 } }
obj.a = obj // 循环援用
const newObj = deepClone(obj)
console.log(newObj.address === obj.address) // false
异步控制并发数
function limitRequest(urls = [], limit = 5) {
return new Promise((resolve, reject) => {
const len = urls.length
let count = 0 // 以后进行到第几个工作
const start = async () => {
const url = urls.shift() // 从数组中拿取第一个工作
if (url) {
try {
await axios.post(url)
if (count == len - 1) {
// 最初一个工作
resolve()
} else {
count++
// 胜利,启动下一个工作
start()
}
} catch (e) {
count++
// 失败,也启动下一个工作
start()
}
}
}
// 启动limit个工作
while (limit > 0) {
start()
limit -= 1
}
})
}
// 测试
limitRequest(['http://xxa', 'http://xxb', 'http://xxc', 'http://xxd', 'http://xxe'])
发表回复