最近更新
7.28 新增了超时时间参数
前言
阅读完本文,大概需要 5 分钟
时间
你将会学到
1. 基础的函数封装思想
2. 函数冗余代码的抽象
项目背景
笔者最近在项目开发阶段,经常遇到这样的场景
当满足 xx 条件的时候,才去执行 xx 函数
,其实最简单的方式就是利用回调函数
为了各位看官能够感同身受
,下面由 boduo
老师为大家上课
场景复现
// 我们初始化一个叫做 `boduo` 的演员,此时 ta 还是八岁
const actor = {
name: 'bodo',
age: 8
}
// 我们再自定义模拟一个时间增长函数
// 假设每 200ms 增长一岁
const ageGrow = () => {
setInterval(() => {
actor.age += 1
// 假设 boduo 长到 18 岁的时候获取到了新技能 movie
if (actor.age >= 18) {
actor.movie = function() {
const { name, age } = actor
console.log(`我叫 ${name},今年${age}岁, 我现在会拍电影啦`)
}
}
}, 200)
}
ageGrow()
场景很简单, 现在有一位经纪人
看中了这位小演员,但是此时 ta 还不会拍电影,所以经纪人
需要每过200ms(一年)
去询问
一下这位小演员是否能够
拍摄电影,不然就可能导致报错翻车
模拟成代码
const makeingMovie = () => {
//actor.movie() //直接调用报错
if (actor.movie) {
actor.movie()
} else {
setTimeout(makeingMovie, 200)
}
}
以上就是我们的常规思路,利用不断轮询
来判断某个条件是否成立
完整的常规代码
const actor = {
name: 'bodo',
age: 8
}
const ageGrow = () => {
setInterval(() => {
actor.age += 1
if (actor.age >= 18) {
actor.movie = function() {
const { name, age } = actor
console.log(`我叫 ${name},今年${age}岁, 我现在会拍电影啦`)
}
}
}, 200)
}
ageGrow()
const makeingMovie = () => {
if (actor.movie) {
actor.movie()
} else {
setTimeout(makeingMovie, 200)
}
}
makeingMovie()
函数封装
简单记录下自己的思路吧 其实无非就是三个条件
- 对应的执行函数
- 对应的条件函数
- 轮询的时间延迟
有了这三个条件,我们能够简单得到以下函数框架
const fn = (executor,condition,delay)=>{}
一开始笔者设计的是没有 return
值的,也就是直接把业务代码在 fn
中执行了,这样的做法就导致耦合度非常高,而且不好传参
借鉴 debounce
防抖的思想,最终决定 return
一个函数出去
const fn = (executor,condition,delay)=>{
if(condition()){
return function(...args){
return executor(...args)
}
}
}
但是condition
的代码需要不断轮询,直接 return
函数并没有什么软用
所以此时又借助了promise
学习
promise 控制并发
技能,强烈推荐各位看官阅读下我这篇文章
封装代码
const getFuncOnLoopCondition = (executor, condition, delay = 10,timeout=10 * 1000) => {
if (typeof executor !== 'function') return console.warn(`getFuncOnLoopCondition'executor must be function,but get ${typeof executor}`)
if (typeof condition !== 'function') return console.warn(`getFuncOnLoopCondition'condition must be function,but get ${typeof condition}`)
const start = performance.now()
let timer = null
return new Promise((resolve, reject) => {
const loop = function(executor, condition, delay) {
if (performance.now() - start > timeout) {
// 超时了
if (timer) clearTimeout(timer)
return reject(`调用超时了`)
}
const finished = condition.apply(this) // 判断条件是否成立
if (finished) {
if (timer) clearTimeout(timer)
const res = function(...args) { // 这里的 args 就是传递给 executor 的
return executor.apply(this, args)
}
resolve(res) // 此时已经满足条件 直接返回函数,函数主体为执行函数
} else {
timer = setTimeout(() => {
loop(executor, condition, delay) // 不断轮询
}, delay)
}
}
loop.call(this, executor, condition, delay)
})
}
下面让我们用封装代码
简单测试一下刚才的场景
const getFuncOnLoopCondition = (executor, condition, delay = 10) => {
if (typeof executor !== 'function') return console.warn(`getFuncOnLoopCondition'executor must be function,but get ${typeof executor}`)
if (typeof condition !== 'function') return console.warn(`getFuncOnLoopCondition'condition must be function,but get ${typeof condition}`)
const start = performance.now()
let timer = null
return new Promise((resolve, reject) => {
const loop = function(executor, condition, delay) {
if (performance.now() - start > timeout) {
// 超时了
if (timer) clearTimeout(timer)
return reject(`调用超时了`)
}
const finished = condition.apply(this)
if (finished) {
if (timer) clearTimeout(timer)
const res = function(...args) {
return executor.apply(this, args)
}
resolve(res)
} else {
timer = setTimeout(() => {
loop(executor, condition, delay)
}, delay)
}
}
loop.call(this, executor, condition, delay)
})
}
const actor = {
name: 'bodo',
age: 8
}
const ageGrow = () => {
setInterval(() => {
actor.age += 1
// 假设 boduo 长到 18 岁的时候获取到了新技能 movie
if (actor.age >= 18) {
actor.movie = function() {
const { name, age } = actor
console.log(`我叫 ${name},今年${age}岁, 我现在会拍电影啦`)
}
}
}, 200)
}
ageGrow()
const executor = (unitPrice) => {
console.log(`售价 ${unitPrice}`)
actor.movie()
}
const condition = () => actor.age >= 18
const makeingMovie = async() => {
// 返回一个 promise 我们需要 借助 async await,或者.then
const fn = await getFuncOnLoopCondition(executor, condition)
const unitPrice = '20元'
fn(unitPrice)
}
makeingMovie()
最后
如果这篇文章对你有帮助,建议小心心大拇指三连🌟
个人能力有限,若有不正确地方,请指出,望读者们不喜勿喷🌟