RequestQueue

A simple queue for GM_xmlhttpRequests or other async functions

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/370011/610040/RequestQueue.js

  1. // ==UserScript==
  2. // @exclude *
  3. // ==UserLibrary==
  4. // @name RequestQueue
  5. // @description A simple queue for GM_xmlhttpRequests or other async functions
  6. // @version 6
  7. // @license MIT
  8. // ==/UserLibrary==
  9. // @namespace cuzi
  10. // @homepageURL https://github.com/cvzi/RequestQueue/
  11. // @grant GM_xmlhttpRequest
  12. // @grant GM.xmlhttpRequest
  13. // ==/UserScript==
  14.  
  15. // ==OpenUserJS==
  16. // @author cuzi
  17. // ==/OpenUserJS==
  18.  
  19. "use strict";
  20.  
  21. function RequestQueue(maxParallel,maxTotal) {
  22. // A simple queue for GM_xmlhttpRequests or other async functions
  23.  
  24. maxParallel = parseInt(maxParallel)>0?parseInt(maxParallel):1;
  25. maxTotal = parseInt(maxTotal)>0?parseInt(maxTotal):Number.POSITIVE_INFINITY;
  26.  
  27. var index = 0; // incrementing, used for unique ids
  28. var finished = 0; // Number of finished requests
  29. var pending = [];
  30. var running = [];
  31. var defaultFunction;
  32. if(typeof GM != "undefined" && "xmlHttpRequest" in GM) {
  33. defaultFunction = GM.xmlHttpRequest;
  34. } else {
  35. defaultFunction = function(a,b,c,d) { return GM_xmlhttpRequest(a,b,c,d);} // Wrap GM_xmlhttpRequest to avoid security exception
  36. }
  37.  
  38.  
  39. /*
  40. The internal request Object extended by add(req,fun,thisArg)
  41. {
  42. __fun : fun, defaults to GM_xmlhttpRequest
  43. __thisArg : thisArg, the this object for the above function
  44. __result : the return value of __fun is saved in this property
  45.  
  46. __org_onload : The original event callbacks of req
  47. __org_onerror
  48. __org_onabort
  49.  
  50. onload : The new event callbacks that wrap the above callbacks
  51. onerror
  52. onabort
  53.  
  54. ... and all the original properties of the "req" object
  55. }
  56.  
  57. */
  58.  
  59. var fire = function() {
  60. // Check for pending requests and send them.
  61. if(pending.length > 0 && running.length < maxParallel && finished < maxTotal) {
  62. var req = pending.shift();
  63. running.push(req);
  64. req.__result = req.__fun.call(req.__thisArg,req);
  65. fire();
  66. }
  67. };
  68.  
  69. var remove = function(id) {
  70. // Remove the request with id from the the running array
  71. for(var i = 0; i < running.length; i++) {
  72. if(running[i].id == id) {
  73. running.splice(i, 1);
  74. finished++;
  75. fire();
  76. break;
  77. }
  78. }
  79. };
  80.  
  81. this.add = function(req,fun,thisArg) {
  82. // Schedule a request: add(req[, fun[, thisArg]])
  83. // fun: defaults to GM.xmlHttpRequest
  84. // thisArg: The value of this provided for the call to fun. Keep strict mode in mind!
  85. req.id = index++;
  86.  
  87. req.__fun = typeof(fun) === 'function'?fun:defaultFunction;
  88. req.__thisArg = thisArg;
  89.  
  90. // Wrap events that indicate that the request has finished
  91. req.__org_onload = req.onload;
  92. req.onload = function(response) {
  93. if(response.status === 0) { // This is true if a request was aborted. This seems to happen only sporadically
  94. req.onabort(response);
  95. return;
  96. }
  97. remove(req.id);
  98. if(req.__org_onload) req.__org_onload(response);
  99. };
  100.  
  101. req.__org_onerror = req.onerror;
  102. req.onerror = function(response) {
  103. remove(req.id);
  104. if(req.__org_onerror) req.__org_onerror(response);
  105. };
  106.  
  107. req.__org_onabort = req.onabort;
  108. req.onabort = function(response) {
  109. remove(req.id);
  110. if(req.__org_onabort) req.__org_onabort(response);
  111. };
  112.  
  113. pending.push(req);
  114. fire();
  115. };
  116.  
  117. this.abortRunning = function() {
  118. // For any added function that was already run: result = thisArg.fun(req)
  119. // it will call result.abort()
  120. // For GM_xmlhttpRequest this will subsequently fire an onabort event
  121. for(var i = 0; i < running.length; i++) {
  122. if(running[i] && typeof running[i].__result.abort === 'function') {
  123. running[i].__result.abort();
  124. }
  125. }
  126. };
  127.  
  128. this.abortPending = function() {
  129. // Clear the pending list
  130. pending = [];
  131. };
  132.  
  133. this.abort = function() {
  134. // Abort both running and pending requests
  135. this.abortPending();
  136. this.abortRunning();
  137. };
  138. this.resetTotal = function() {
  139. // Reset number of finished requests
  140. finished = 0;
  141. }
  142. this.hasReachedTotal = function() {
  143. // Number of maximum allowed requests reached?
  144. return finished >= maxTotal;
  145. }
  146. this.hasRunning = function() {
  147. // Are there any running requests?
  148. return running.length > 0;
  149. }
  150. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址