Search code examples
javascriptpromisees6-promise

How to create a pending request list while allowing the promise to hang?


class Network {
  constructor() {
    this.concurrency = 0
    this.pending = []
  }
  request(data) {
    if (this.concurrency <= 10) {
      ++this.concurrency
      return request({
        ...data
      }).finally(res =>{
        --this.concurrency
        this.pending.forEach(data => {
          this.request(data)
        })
        return res
      })
    } else {
      this.pending.push(data)
      return new Promise(...)
    }
  }
}

What I am trying to do is to limit the concurrent request to 10, and let the excessive request to queue and return a pending promise until the concurrent request drop from 10...

Obviously the above code wouldn't work because this.pending is disconnected from the new Promise...

This is how I did it eventually:

class Network {
  constructor() {
    this.concurrency = 0
    this.pending = []
  }
  ajax = data => new Promise(resolve => {
    if (this.concurrency <= 10) {
      ++this.concurrency
      return resolve( this.send(data) )
    } else {
      return this.pending.push({ data, resolve })
    }
  })
  send = data => new Promise(resolve => {
    return request({
      ...data
    }).finally(res => {
      --this.concurrency
      if (this.pending.length)
        for (let request of this.pending) {
          request.resolve( this.ajax(request.data) )
          this.pending.shift()
        }
    })
  })
}

Solution

  • class Network {
      constructor() {
        this.concurrency = 0
        this.pending = []
      }
    
      async request(data) {
        if (this.concurrency > 10) {
          await this.queue();
        }
        // Make the actual request
        // Increment the concurrency count
        // call `this.next()` after success of every call
      }
    
      queue () {
        return new Promise((resolve, reject) => {
          this.pending.push({resolve, reject});
        })
      }
    
      next () {
        this.concurrency--;
        if (this.concurrency < 10 && this.pending.length) {
          let newReq = this.pending.splice(0, 1);
          newReq.resolve();
        }
      }
    }