前言:暂时先粗解10题。题目会不按期更新(解题若有误,可在评论区贴出~你们共同窗习进步)node
/**
* 【模拟Promise】
*/
class myPromise {
constructor(callback) {
this.status = 'pending'
this.resMsg = ''
this.errMsg = ''
this.successCallBack = null
this.errCallBack = null
callback((res) => {
this.resMsg = res
this.successCallBack && this.successCallBack(this.resMsg) // pending ==> resolved 状态时, 如有暂存回调函数, 读取暂存回调函数
this.status = 'resolved'
}, (err) => {
this.errMsg = err
this.errCallBack && this.errCallBack(this.errMsg)
this.status = 'rejected'
})
this.callback = callback
}
then(successCallBack) {
console.log('---- then ---', this.status)
if(this.status === 'resolved') {
successCallBack(this.resMsg)
}
if(this.status === 'pending') {
console.log(successCallBack)
this.successCallBack = successCallBack // 若是还在pending状态,先暂存回调函数
}
return this;
}
catch(errCallBack) {
console.log('---- catch ---', this.status)
if(this.status === 'rejected') {
errCallBack(this.errMsg)
}
if(this.status === 'pending') {
console.log(errCallBack)
this.errCallBack = errCallBack
}
return this;
}
}
/**
* 测试用例一
*/
new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('测试success')
}, 2000)
}).then(res => {
console.log('res', res)
}).catch(err => {
console.log('err', err)
})
/**
* 测试用例二
*/
new myPromise((resolve, reject) => {
setTimeout(() => {
reject('测试error')
}, 5000)
}).then(res => {
console.log('res', res)
}).catch(err => {
console.log('err', err)
})
复制代码
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 3000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 4000);
})
let p3 = Promise.reject('失败')
/**
* 【模拟Promise.all】
*/
class myPromise{
constructor() {
}
static all(promises) {
// 确保promises为array
if(!Array.isArray(promises)) {
throw new Error('大哥,麻烦输入promise数组啊')
}
let results = []
let isRejected = false
return new Promise((resolve, reject) => {
promises.map((item, index) => {
item.then(res => {
if(!isRejected) {
results.push(res)
if(index === promises.length - 1) {
promises.length === results.length && resolve(results)
}
}
}).catch(err => {
reject(err)
isRejected = true
})
})
})
}
}
myPromise.all([p1,p2]).then(res => {
console.log(res, 'res1')
}).catch(err => {
console.log(err, 'err1')
})
myPromise.all([p1,p2,p3]).then(res => {
console.log(res, 'res2')
}).catch(err => {
console.log(err, 'err2')
})
复制代码
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 3000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败了')
}, 1000);
})
class myPromise{
constructor() {
}
static race(promises) {
// 确保promises为array
if(!Array.isArray(promises)) {
throw new Error('大哥,麻烦输入promise数组啊')
}
let hasResult = false
return new Promise((resolve, reject) => {
promises.map((item, index) => {
item.then(res => {
hasResult || resolve(res)
hasResult = true
}).catch(err => {
hasResult || reject(err)
hasResult = true
})
})
})
}
}
myPromise.race([p1,p2]).then(res => {
console.log(res, 'res1')
}).catch(err => {
console.log(err, 'err1')
})
复制代码
// Tips: 并发20个promise,并发上限是10个,队列先入队前10个promise,其中有promise执行成功,队列外剩余的promise依次入队(保证队列中始终保持10个上限)web
// 生成promise
const fetch = (duration , index) => {
return function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({duration, index})
}, duration);
})
}
}
/**
* 控制promise并发数 (暂时默认所有 success)
* Tips: Promise实例化后,即开始执行。因此promise数超上限时,暂时解决方案是:先初始化limit个promise,以后
*
* @param {Number} total 总promise条数
* @param {Number} max 最大并发数
* @param {Funtion} callback 全部promise执行后的回调
* @return
*/
const concurrencyFetch = (total, max, callback) => {
let currentFetchs = [];
let maxlen = Math.min(total, max)
let i = 0;
fetchs = initPromises(total)
// 请求数 未达到并发上限, 直接走promise.all便可
if(fetchs.length < max) {
Promise.all(fetchs.reduce((total, item) => {
return [...total, item.pro()]
}, [])).then(() => {
callback('所有执行完了')
})
return false;
}
currentFetchs = fetchs.slice(0, max)
// 达到最大并发数
function concurrencyLimit() {
/* currentFetchs.splice() */
/* let currentFetchs = fetchs.slice(i, i + max) */
/* console.log('---------达到并发瓶颈了---------', i, fetchs) */
console.log('当前---', i, currentFetchs)
debugger
Promise.race(currentFetchs.reduce((total, item) => {
return [...total, item.pro()]
}, [])).then((res) => {
if(max + i < total) {
const removeIndex = currentFetchs.findIndex(item => item.index === res.index)
let fastPromise = currentFetchs.splice(removeIndex, 1)
console.log('移除队列中最快执行的promise:', fastPromise)
i++;
currentFetchs = [...currentFetchs, fetchs[max + i - 1]]
concurrencyLimit()
} else {
// 已经所有塞入 currentFetchs队列
Promise.all(currentFetchs.reduce((total, item) => {
return [...total, item.pro()]
}, [])).then(() => {
callback('所有执行完了')
})
}
})
}
concurrencyLimit()
}
// 生成promise list
const initPromises = (len, startIndex = 0) => {
let arr = [];
new Array(len).fill('').map((_ , i) => {
let randomNum = Math.floor(Math.random()*10 + 1) * 1000
arr.push({pro: fetch(randomNum, startIndex + i), index: startIndex + i, randomNum})
})
console.log('生成的promise列表: ', arr)
return arr
}
concurrencyFetch(15 , 10, (res) => {
console.log(res, '都ok了~')
})
复制代码
// Tips: 暂时只想到两种,有其余方案的能够评论区留言哈~数组
实现方案一:(async await | promise) 我的感受是最容易想到的方案promise
/**
* 线程阻塞
*
* @param {Number}
* @return
*/
const sleep = async (delay) => {
const pro = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`----- 线程阻塞 ${delay/1000} s了 -----`)
}, delay);
})
const res = await pro
console.log(res)
}
复制代码
实现方案二:(时间戳) 浏览器
const sleep = async (delay) => {
const startTime = new Date().getTime();
console.log(startTime)
while(new Date().getTime() - startTime < delay) {
continue
}
console.log(`----- 线程阻塞 ${delay/1000} s了 -----`)
}
复制代码
LazyMan(“Hank”)输出: Hi! This is Hank!bash
LazyMan(“Hank”).sleep(10).eat(“dinner”) 输出 Hi! This is Hank! //等待10秒.. Wake up after 10 Eat dinner~闭包
LazyMan(“Hank”).eat(“dinner”).eat(“supper”) 输出 Hi This is Hank! Eat dinner~ Eat supper~并发
以此类推。dom
class LazyMan {
constructor(name) {
this.name = name
this.asyncFun = Promise.resolve(this)
console.log(`--------- Hi This is ${this.name}! ---------`)
}
sleep(delay) {
console.log('sleep')
this.asyncFun = this.asyncFun.then(() => {
return new Promise(resolve => {
setTimeout(() => {
console.log(`--------- Wake up after ${delay/1000}s ----------`)
resolve()
}, delay);
})
})
return this; //提供 ”链式调用“
}
eat(food) {
console.log('eat')
this.asyncFun = this.asyncFun.then(res => {
console.log(`--------- Eat ${food}~ ---------`)
return Promise.resolve()
})
return this;
}
}
new LazyMan('小菜比').sleep(4000).eat('豆浆').eat('油条').sleep(2000).eat('炒年糕')
复制代码
举个例子:冲啊,兄弟们,拿lol首胜赚金币了。。。腾讯baba为了防止你被拉去杨教授那电疗,首胜的周期是一天一次。若是不设置周期,每盘都能触发首胜。。。你怕是要累趴在电脑前。。。 这就是咱们传说中的 节流 async
/**
* 节流
*
* @param {Function} fn 须要节流的函数
* @param {Number} duration 触发fn间隔时间, 单位ms
* @param {Boolean} immediately 是否当即执行
* @return
*/
function throttle (fn, duration, immediately = true) {
let timer = null
// 为啥用闭包??? 把局部变量驻留在内存,避免使用全局变量
return function() {
if(!timer) {
if(immediately) {
fn()
timer = setTimeout(() => {
timer = null
}, duration);
} else {
timer = setTimeout(() => {
fn()
timer = null
}, duration);
}
}
}
}
function show() {
console.log('优雅的切图仔')
}
setInterval(throttle(show, 5000, true), 1000);
复制代码
举个例子: 我要减肥(固然博主并不须要减肥,反而须要增肥,哈哈)???立个flag...劳资15天不吃肉!谁吃谁煞b。。一天两天我咬牙坚决信念,终于13天过去了,第十四天(我。。。实在忍忍忍不住了,偷偷吃了包猪肉铺,nice成功“破戒了”,15天flag从新刷新,前功尽弃咯。。。) 这就是咱们传说中的 防抖
/**
* 防抖
*
* @param {Function} fn 须要防抖的函数
* @param {Number} duration 禁止触发fn的间隔, 单位ms
* @param {Boolean} immediately 是否当即执行
* @return
*/
function debounce(fn, duration, immediately = true) {
let timer = null
// 为啥用闭包??? 把局部变量驻留在内存,避免使用全局变量
return function() {
if(immediately) {
timer ? clearTimeout(timer) : fn()
timer = setTimeout(() => {
timer = null
}, duration);
} else {
timer && clearTimeout(timer)
timer = setTimeout(() => {
timer = null
fn()
}, duration);
console.log(timer)
}
}
}
复制代码
function add(...args) {
let radixPointArr = args.reduce((total, item) => {
item = '' + item
let itemRadixPoint = item.indexOf('.')
if(itemRadixPoint >= 1) {
return [...total, item.length - itemRadixPoint - 1]
} else {
return [...total, 0]
}
}, [])
const radixLen = Math.max(...radixPointArr)
const result = args.reduce((total,item) => {
return total + item * Math.pow(10,radixLen)
}, 0)
return result / Math.pow(10,radixLen)
}
add(0.1,0.222,0.3, 3232, 0.66666)
复制代码
/**
* 【localStorage设置时效性】
*
* Tips: 这个就不要在node里跑了。web storage 针对浏览器~
* @param {String} key
* @param {Any} value
* @param {Number} expired 保质期 单位“秒”(这时候,一批吃货投来“不屑”的目光)
*/
class myStorage {
constructor() {
}
// 默认无限大,暂时就99999999s吧~
static set(key, value, expired = 99999999) {
localStorage.setItem(key, JSON.stringify({
value,
expiredTimestamp: new Date().getTime() + expired * 1000
}));
}
static get(key) {
if(localStorage.getItem(key)) {
let result = JSON.parse(localStorage.getItem(key))
console.log(result)
const nowTimestamp = new Date().getTime()
if(nowTimestamp > result.expiredTimestamp) {
console.log('都过时了,看你妹啊~')
this.remove(key)
} else {
console.log(result.value)
}
} else {
console.log('storage已经被删除了,赶忙去建立一个吧~')
}
}
static remove(key) {
localStorage.getItem(key) && localStorage.removeItem(key)
}
}
myStorage.set('name', '我是小菜比', 10)
myStorage.get('name')
复制代码
实现add(1)(2)(3) = 6; add(1, 2, 3)(4) = 10; add(1)(2)(3)(4)(5) = 15;
复制代码