备注:

使用promise对并发请求进行封装,可支持并发请求任务个数及任务优先级。
原理:使用队列的数据结构 ,先进先出的处理请求,如添加任务优先级高的任务,
则会通过数组的shift()方法插入到队列的头部

mock.js文件:

  1. const urls = [
  2. {
  3. info: 'task1',
  4. timeout: 3000,
  5. sort: 1,
  6. },
  7. {
  8. info: 'task2',
  9. timeout: 1000,
  10. sort: 1,
  11. },
  12. {
  13. info: 'task3',
  14. timeout: 2000,
  15. sort: 3,
  16. },
  17. {
  18. info: 'task4',
  19. timeout: 1000,
  20. sort: 2,
  21. },
  22. {
  23. info: 'task5',
  24. timeout: 5000,
  25. sort: 1,
  26. },
  27. {
  28. info: 'task6',
  29. timeout: 3000,
  30. sort: 6,
  31. },
  32. ];
  33. const loadingImg = ({ info, timeout }) => {
  34. return new Promise((res, rej) => {
  35. setTimeout(() => {
  36. res(info);
  37. }, timeout);
  38. });
  39. };
  40. module.exports = { urls, loadingImg };

promise封装:

支持并发数量:

  1. const { urls, loadingImg } = require('./mock');
  2. class PromiseQueue {
  3. constructor(options) {
  4. this.maxCurry = options.maxCurry;
  5. this.currentCount = 0;
  6. this.pendingList = [];
  7. }
  8. addTask(fn) {
  9. this.pendingList.push(fn);
  10. this.runTask();
  11. }
  12. runTask() {
  13. if (!this.pendingList.length || this.currentCount === this.maxCurry) return;
  14. this.currentCount++;
  15. const fn = this.pendingList.shift();
  16. const promise = fn();
  17. promise.then(this.restartRunTask.bind(this)).catch(this.restartRunTask.bind(this));
  18. }
  19. restartRunTask() {
  20. this.currentCount--;
  21. this.runTask();
  22. }
  23. }
  24. const queue = new PromiseQueue({ maxCurry: 3 });
  25. urls.forEach((url) => {
  26. queue.addTask(() => loadingImg(url));
  27. });

支持任务优先级:

添加高优任务不会取消当前已经发出的请求,而是放在发出请求后的队列的头部

  1. const { urls, loadingImg } = require('./mock');
  2. class PromiseQueue {
  3. constructor(options) {
  4. this.maxCurry = options.maxCurry;
  5. this.currentCount = 0;
  6. this.pendingList = [];
  7. }
  8. addTask(fn) {
  9. this.pendingList.push(fn);
  10. if (this.pendingList.length > 1) {
  11. this.pendingList = this.pendingList.sort((a, b) => b.sort - a.sort);
  12. }
  13. this.runTask();
  14. }
  15. runTask() {
  16. if (!this.pendingList.length || this.currentCount === this.maxCurry) return;
  17. this.currentCount++;
  18. const { fn } = this.pendingList.shift();
  19. const promise = fn();
  20. promise.then(this.restartRunTask.bind(this)).catch(this.restartRunTask.bind(this));
  21. }
  22. restartRunTask() {
  23. this.currentCount--;
  24. this.runTask();
  25. }
  26. }
  27. const queue = new PromiseQueue({ maxCurry: 3 });
  28. const formatTask = (url) => {
  29. return {
  30. fn: () => loadingImg(url),
  31. sort: url.sort,
  32. };
  33. };
  34. urls.forEach((url) => {
  35. queue.addTask(formatTask(url));
  36. });
  37. queue.addTask(
  38. formatTask({
  39. info: 'high!!!',
  40. timeout: 2000,
  41. sort: 10,
  42. }),
  43. );