同事大番薯说请假几天,人走之后领导说其实是离职了,留下的代码我来接手......面对一团毛线团,我是无语凝噎。
在维护期间,发现一个需求是在 Select 存在选中的 Option 时再切换需要提示用户会清空关联数据,是否确认切换。
大番薯原来的逻辑是维护了一个 state { isLock: Boolean },在切换时先检查 isLock,默认为 false 不提示正常切换,选中后置为 true,再切换就提示,确认切换再重置为 false。
这种方法也不是不行,但是想到之前读 qiankun 源码看到根据 Promise 状态确定其生命周期执行流程的那段代码,我打算把函数锁定执行这个逻辑提取成一个方法。在我打算动手之前正好在 B 站看到一个新人 up 上传了一个完整的 demo promise 加锁与解锁。所以直接拿来用了,完善了一些小细节。以下为具体步骤。
首先,该方法希望可以锁定、解锁和执行被传入的任一函数。
function lockPlant() {
const fnMap = {};
return function(fn) {
fnMap[fn.name] = {
callback: fn,
lock: function() {},
unLock: function() {},
[fn.name]: function() {
this.callback && this.callback();
}
};
return fnMap[fn.name];
}
};
其次,锁定功能和解锁使用 Promise 的延迟执行。
function lockPlant() {
const fnMap = {};
return function(fn) {
fnMap[fn.name] = {
callback: fn,
lock: function() {
new Promise(_resolve => {
this.resolve = _resolve;
})
},
unLock: function() {
this.resolve();
},
[fn.name]: function() {
this.callback && this.callback();
}
};
return fnMap[fn.name];
}
};
将锁定、解锁功能和原函数关联起来。
function lockPlant() {
const fnMap = {};
return function(fn) {
fnMap[fn.name] = {
callback: fn,
lock: function() {
this.status = new Promise(_resolve => {
this.resolve = _resolve;
})
},
unLock: function() {
this.resolve();
},
[fn.name]: function() {
if(this.status) {
this.status.then(() => {
this.callback && this.callback();
this.status = null;
})
} else {
this.callback && this.callback();
}
}
};
return fnMap[fn.name];
}
};
添加检测是否被锁定函数功能和被传入的函数接收传入参数。
function lockPlant() {
const fnMap = {};
return function(fn) {
fnMap[fn.name] = {
callback: fn,
isLock: function(){
return !!this.status;
},
lock: function() {
this.status = new Promise(_resolve => {
this.resolve = _resolve;
})
},
unLock: function() {
this.resolve();
},
[fn.name]: function(...arg) {
if(this.status) {
this.status.then(() => {
this.callback && this.callback(...arg);
this.status = null;
})
} else {
this.callback && this.callback(...arg);
}
}
};
return fnMap[fn.name];
}
};
写个测试函数检测一下
const lockInstance = lockPlant();
function test(msg) {
console.log(`hello ${msg}`);
}
const t = lockInstance(test);
t.test("word"); // 立即执行
t.lock();
t.test("word again"); // 延迟 3 秒后执行
if(t.isLock()) {
setTimeout(() => {
t.unLock();
}, 3000);
}
搞定,收工。