Execute batch of promises in series. Once Promise.all is done go to the next batch

后端 未结 6 1322
猫巷女王i
猫巷女王i 2021-02-19 15:57

I have an array that contains an array of promises, and each inner array could have either 4k, 2k or 500 promises.

In total there are around 60k promises and I may test

6条回答
  •  孤城傲影
    2021-02-19 16:54

    Dynamically batching more promises

    A simple implementation where you can have a queue of tasks batched to run in parallel and add more dynamically:

    class TaskQueue {
      constructor ({
        makeTask,
        initialData = [],
        getId = data => data.id,
        batchSize = 15,
        onComplete = () => {},
      }) {
        if (!makeTask) throw new Error('The "makeTask" parameter is required');
    
        this.makeTask = makeTask;
        this.getId = getId;
        this.batchSize = batchSize;
        this.onComplete = onComplete;
        this.queue = new Map();
    
        this.add(initialData);
      }
    
      add(...data) {
        data.forEach(item => {
          const id = this.getId(item);
          if (this.queue.has(id)) return;
    
          this.queue.set(id, item);
        });
    
        // running automatically on create or additional items added
        this.runNextBatch();
      }
    
      runNextBatch () {
        if (this.queueStarted) return;
        if (this.queue.size === 0) return;
    
        this.queueStarted = true;
        const currentBatchData = Array.from(this.queue.values()).slice(0, this.batchSize);
    
        const tasks = currentBatchData.map(data => {
          const id = this.getId(data);
    
          // Have some error handling implemented in `makeTask`
          this.makeTask(data)
            .finally(() => this.queue.delete(id));
        });
    
        return Promise.all(tasks)
          .then(() => {
            this.queueStarted = false;
            this.runNextBatch();
          })
          .finally(() => {
            this.queueStarted = false;
            if (this.queue.size === 0) this.onComplete();
          });
      }
    }
    
    // Usage
    const lotOfFilesForUpload = [{ uri: 'file://some-path' }, { uri: 'file://some-other-path' }];
    
    const upload = (file) => console.log('fake uploading file: ', file);
    
    const taskQueue = new TaskQueue({
      initialData: lotOfFilesForUpload,
      getId: file => file.uri,
      makeTask: file => upload(file),
      onComplete: () => console.log('Queue completed'),
    });
    
    // You can add more tasks dynamically
    taskQueue.add({ uri: 'file://yet-another-file' });
    
    

提交回复
热议问题