Javascript,设计一个可取消函数

268 阅读2分钟

一.设计思路

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
      }

    },
  }

}