什么,你还不会使用异步条件函数?
前言
在我们项目开发中,经常会遇到当满足 xx 条件的时候,才去执行 xx 函数
其实最简单的方式就是利用回调函数
。
但是这样做业务耦合性太强, 接下来 让我们一步步来实现一个通用异步条件函数
业务场景模拟
不知道 大家最近股市收益如何? 接下来让我们来模拟茅台股的购买
假设你是一位股民,此时账户金额为 0
, 每 20ms
账户金额会增加 100
今天的茅台股价为 10000
常规业务代码
const user = {
name: 'user1',
account: 0
}
user.buy = function(stock,price) {
if(user.account<price) return console.log(`余额${user.account}不足,不能购买${stock}`)
console.log(`我的账户金额达到了 ${user.account},此时可以购买${stock}了`)
}
/*
模拟后台行为
每 20ms 账户金额自动增加100
达到 10000 的时候可以购买茅台
*/
const accountGrow = () => {
setInterval(() => {
user.account += 100
}, 20)
}
accountGrow()
/* 模拟后台行为end */
const fn = () => {
if (user.account>=10000) {
user.buy('茅台',10000)
} else {
setTimeout(fn, 200)
}
}
fn()
以上就是我们的常规思路,利用不断轮询
来判断某个异步条件是否成立
通用函数设计
简单记录下自己的设计思路吧,其实无非就是三个参数
- 异步执行函数
- 异步条件函数
- 轮询的时间参数
有了这三个条件,我们设计的函数签名如下
const fn = (asyncExecutor,asyncCondition,delay)=>{}
进一步解耦
一开始笔者设计的是没有 return
值的,也就是直接把业务代码在 fn
中执行了
这样的做法就导致耦合性
非常高,并且 不好进行参数的传递
借鉴 debounce
防抖的思想,最终决定 return
一个函数出去, 大致结构如下
const fn = (asyncExecutor,asyncCondition,delay)=>{
if(asyncCondition()){
return function(...args){
return asyncExecutor(...args)
}
}
}
但是condition
的代码需要不断轮询,直接 return
函数并没有什么软用
所以此时又借助了promise
完整代码
其实函数设计思路
有了,写代码 对各位彦祖
来说,就是小意思了
const getAsyncExecutor = (asyncExecutor, asyncCondition, options={delay:10,timeout:10 * 1000}) => {
if (typeof asyncExecutor !== 'function') return console.warn(`asyncExecutor must be function,but get ${typeof asyncExecutor}`)
if (typeof asyncCondition !== 'function') return console.warn(`asyncCondition must be function,but get ${typeof asyncCondition}`)
const {delay,timeout} = options
const start = performance.now()
let timer = null
return new Promise((resolve, reject) => {
const loop = function(asyncExecutor, asyncCondition, delay) {
if (performance.now() - start > timeout) {
// 超时了
if (timer) clearTimeout(timer)
return reject(`调用超时了`)
}
const finished = asyncCondition.apply(this)
if (finished) {
if (timer) clearTimeout(timer)
const res = function(...args) {
return asyncExecutor.apply(this, args)
}
resolve(res)
} else {
timer = setTimeout(() => {
loop.call(this, asyncExecutor, asyncCondition, delay)
}, delay)
}
}
loop.call(this, asyncExecutor, asyncCondition, delay)
})
}
下面让我们用封装代码
简单测试一下刚才的场景
/*
模拟后台行为
每 20ms 账户金额自动增加100
达到 10000 的时候可以购买茅台
*/
const user = {
name: 'user1',
account: 0
}
user.buy = function(stock,price) {
if(user.account<price) return console.log(`余额${user.account}不足,不能购买${stock}`)
console.log(`我的账户金额达到了 ${user.account},此时可以购买${stock}了`)
}
const accountGrow = () => {
setInterval(() => {
user.account += 100
}, 20)
}
accountGrow()
/* 模拟后台行为end */
const executor = (data) => {
console.log('🚀 ~ executor ~ data:', data)
user.buy('茅台',10000)
}
const condition = () => user.account >= 10000
// 返回一个 promise 我们需要 借助 async await,或者.then
getAsyncExecutor(executor, condition).then(asyncExecutor=>{
asyncExecutor('终于能买茅台了')
})
写在最后
个人能力有限 如有不对,欢迎指正🌟 如有帮助,建议小心心大拇指三连🌟
彩蛋
宁波团队还有一个hc, 带你海鲜自助
。 欢迎彦祖们私信😚
转载自:https://juejin.cn/post/7270831230076239930