一.设计思路
1.思考:
创建一个支持未执行可取消的函数,首先就考虑到利用闭包完成,这个函数应该接受一个函数作为参数,其中闭包内部应该有一个状态标识变量来控制这个函数是否可执行,甚至于可以告诉我们函数执行的时机,还应该返回2个控制函数,一个是控制函数是否执行,另一个是控制函数是否取消执行。按照思考,我们可以写出如下代码:
function creatCancellableFunction (callback) {
const obj = {
handle: callback,
// 0: 未执行 1: 执行中 2: 执行完毕 3: 取消执行
status: 0,
}
return {
cancel: function () {
obj.status = 3
},
handle: async function () {
obj.result = await obj.handle.apply(this, arguments)
return obj.result
},
}
}
2.完善代码
首先我们需要在确定哪些状态时可以正常执行的,如果我们调用取消函数cancel的时候,应该确保这个函数处于未执行状态或者一区取消过执行,当函数正在执行或者执行完毕的时候,我们应该抛出相应的错误(或者打印出不能取消的原因),如果我们调用hanlle函数的的时候吗,应该确保这个函数未被取消执行,或者没有正在执行中,完善代码如下:
function creatCancellableFunction (callback) {
const obj = {
handle: callback,
// 0: 未执行 1: 执行中 2: 执行完毕 3: 取消执行
status: 0,
}
return {
cancel: function () {
if ([1].includes(obj.status)) {
console.log('无法取消,方法正在执行中')
} else if ([2].includes(obj.status)) {
console.log('无法取消,方法已执行完毕')
} else if ([0, 3].includes(obj.status)) {
console.log('方法取消成功')
// 设置方法状态:取消执行
obj.status = 3
} else {
console.log('无法取消,未知状态')
}
},
handle: async function () {
if ([3].includes(obj.status)) {
console.log('方法已取消,无法继续执行')
return
} else if ([1].includes(obj.status)) {
console.log('无法重复执行,方法正在执行中')
return
}
try {
// 设置方法状态:正在执行中
obj.status = 1
obj.result = await obj.handle.apply(this, arguments)
return obj.result
} catch (e) {
throw `Error: ${e}`
} finally {
console.log('方法执行完毕')
// 若只允许设置方法为只能执行一次,则将状态设置为已执行完毕
obj.status = 2
// 若允许设置方法为可多次执行,则将状态设置为0 未执行
// obj.status = 0
}
},
}
}