最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 记一次在面试过程中遇到的 promise 编程题

    正文概述 掘金(SoulReader)   2021-04-01   401

    昨天面试的时候遇到了这两个函数编程题,但是该死的是完全没有思路(悲伤)

    1. 利用 Promise 完成一个队列,队列中的任务数满了的话,后续任务不执行,当队列中的任务有完成的状态,才会添加新的任务进入队列

    2. 完成一个 retry 函数,传入一个执行函数和一个计数器,在一定次数范围内,如果函数执行失败的话会再次尝试执行该函数,直到执行成功

    面试结束之后,我上网上搜索了一下类似的问题,接下来是我总结之后的思路,以及最后成功的代码

    Promise 队列

    这个问题有以下几个重点

    • 队列: 存放未执行的任务队列
    • 计数器: 存放当前正在执行的任务数量
    • 任务执行最大数量
    • 添加任务函数
    • 执行任务函数

    接下根据我们上述描述的重点来创建一个任务队列执行类

      class Scheduler {
        // 初始化任务队列,以及根据传入的数量来限制最大执行数量
        constructor(maxCount) {
          this.maxCount = count
          this.list = []
          this.count = 0
        }
        add() {
    
        }
        start() {
    
        }
      }
    

    接下我们就要来编写添加函数了,在写添加函数之前我们首先思考一下这个添加函数里面应该注意那些东西

    首先,如果我们想要在任务执行完成之后对执行结果操作的话,这个 add 函数必须返回一个 promise 函数

      add(task) {
        return new Promise(resolve => {
          resolve()
        })
      }
    

    添加一个任务的时候,我们需要把这个任务添加到未执行的任务队列的存放起来

      add(task) {
        return new Promise(resolve => {
          resolve(() => {
            this.list.push(task())
          })
        })
      }
    

    这个时候就出现了一个问题,我们应该怎样监控这个任务是否已经执行完成,这个时候 promise 的作用就来了,我们在 then 中就可以判断到函数是否执行成功

      add(task) {
        return new Promise(resolve => {
          resolve(() => {
            this.list.push(Promise.resolve(task()).then())
            // 如果 task 执行之后的返回值是一个promise对象则可以修改成以下形式
            // this.list.push(task().then())
          })
        })
      }
    

    添加函数先写到这里,然后我们来写执行函数,在start函数中我们需要做的就是判断一下正在执行任务数是否小于最大执行数,然后从待执行队列中取出一个任务并执行,然后将正在执行的任务数加上1

      start() {
        if(this.count < this.maxCount) {
          this.count++
          this.list[0] && this.list.shift()()
        }
      }
    

    接下来修改 add 函数 为当我们添加一个任务时,在最后执行一下执行函数,在执行任务完成之后,减少执行队列数,并触发执行函数,最后把任务的返回值 return 出来

      add(task) {
        return new Promise(resolve => {
          this.list.push(() => {
            resolve(Promise.resolve(task()).then(s => {
              this.count--
              this.start()
              return s
            }))
          })
          this.start()
        })
      }
    

    接下来实例化任务队列,并创建一个异步执行方法和一个添加任务函数

      let scheduler = new Scheduler(5)
      let timeout = (time) => {
        return new Promise(resolve => {
          setTimeout(resolve, time)
        })
      }
    
      let addTask = function addTask(time, order) {
        scheduler.add(() => timeout(time)).then(() => {
          console.log(time, order)
        })
      }
    

    附上完整代码

    class Scheduler {
    constructor(count) {
      this.list = []
      this.maxCount = count
      this.count = 0
    }
    add(task) {
      return new Promise(resolve => {
        this.list.push(() => {
          resolve(Promise.resolve(task()).then(s => {
            this.count--
            this.start()
            return s
          }))
        })
        this.start()
      })
    }
    start() {
      console.log(this.count)
      if(this.count < this.maxCount) {
        this.count++
        this.list[0] && this.list[0]()
        this.list.shift()
      }
    }
    }
    
    let scheduler = new Scheduler(5)
    let timeout = (time) => {
    return new Promise(resolve => {
      setTimeout(resolve, time)
    })
    }
    
    let addTask = function addTask(time, order) {
    scheduler.add(() => timeout(time)).then(() => {
      console.log(time, order)
    })
    }
    
    addTask(5000,'1')
    addTask(1100,'2')
    addTask(2200,'3')
    addTask(3300,'4')
    addTask(3300,'5')
    addTask(3300,'6')
    addTask(3300,'7')
    addTask(2200,'8')
    

    retry 函数

    function retry(fun, count) {
      if(count === 0) return
      let val = fun()
      if(val > 3) {
        return val
      } else {
        return retry(fun, --count)
      }
    }
    
    function random() {
      return Math.random() * 5
    }
    console.log(retry(random, 5))
    

    这个问题现在看起来挺简单的,但是当时估计相差了,思路都理解错了,难受


    起源地下载网 » 记一次在面试过程中遇到的 promise 编程题

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元