AsyncQueue.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import { Framework } from "../Framework";
  2. export type NextFunction = (nextArgs?: any) => void;
  3. export type AsyncCallback = (next: NextFunction, params: any, args: any) => void;
  4. interface AsyncTask {
  5. /**
  6. * 任务uuid
  7. */
  8. uuid: number;
  9. /**
  10. * 任务开始执行的回调
  11. * params: push时传入的参数
  12. * args: 上个任务传来的参数
  13. */
  14. callbacks: Array<AsyncCallback>;
  15. /**
  16. * 任务参数
  17. */
  18. params: any
  19. }
  20. export class AsyncQueue {
  21. private _runningAsyncTask: AsyncTask = null; //正在运行的任务
  22. private static _$uuid_count: number = 1; //任务task的唯一标识
  23. private _queues: Array<AsyncTask> = []; //任务队列
  24. complete: Function | null = null; //任务队列完成回调
  25. get queues(): Array<AsyncTask> {
  26. return this._queues;
  27. }
  28. private _isProcessingTaskUUID: number = 0; //正在执行的异步任务标识
  29. private _enable: boolean = true; //是否启动
  30. /**
  31. * 是否开启可用
  32. */
  33. get enable() {
  34. return this._enable;
  35. }
  36. /**
  37. * 是否开启可用
  38. */
  39. set enable(val: boolean) {
  40. if (this._enable !== val) {
  41. this._enable = val;
  42. if (val && this.size > 0) {
  43. this.play();
  44. }
  45. }
  46. }
  47. /**
  48. * push一个异步任务到队列中
  49. * 返回任务uuid
  50. */
  51. push(callback: AsyncCallback, params: any = null) {
  52. let uuid = ++AsyncQueue._$uuid_count;
  53. this._queues.push({
  54. uuid: uuid,
  55. callbacks: [callback],
  56. params: params
  57. })
  58. return uuid;
  59. }
  60. /**
  61. * push多个任务,多个任务函数会同时执行,
  62. * 返回任务uuid
  63. */
  64. pushMulti(params: any, ...callbacks: AsyncCallback[]) {
  65. let uuid = ++AsyncQueue._$uuid_count;
  66. this._queues.push({
  67. uuid: uuid,
  68. callbacks: callbacks,
  69. params: params
  70. })
  71. return uuid;
  72. }
  73. /** 移除一个还未执行的异步任务 */
  74. remove(uuid: number) {
  75. if (this._runningAsyncTask?.uuid === uuid) {
  76. console.error("正在执行的任务不可以移除");
  77. return;
  78. }
  79. for (let i = 0; i < this._queues.length; ++i) {
  80. if (this._queues[i].uuid === uuid) {
  81. this._queues.splice(i, 1);
  82. break;
  83. }
  84. }
  85. }
  86. /**
  87. * 队列长度
  88. */
  89. get size(): number {
  90. return this._queues.length;
  91. }
  92. /**
  93. * 是否有正在处理的任务
  94. */
  95. get isProcessing(): boolean {
  96. return this._isProcessingTaskUUID > 0;
  97. }
  98. /**
  99. * 队列是否已停止
  100. */
  101. get isStop(): boolean {
  102. return (this._queues.length > 0 || this.isProcessing) ? false : true;
  103. }
  104. /** 正在执行的任务参数 */
  105. get runningParams() {
  106. return this._runningAsyncTask ? this._runningAsyncTask.params : null;
  107. }
  108. /**
  109. * 清空队列
  110. */
  111. clear() {
  112. this._queues = [];
  113. this._isProcessingTaskUUID = 0;
  114. this._runningAsyncTask = null;
  115. }
  116. protected _next_task(taskUUID: number, args: any = null) {
  117. if (this._isProcessingTaskUUID === taskUUID) {
  118. this._isProcessingTaskUUID = 0;
  119. this._runningAsyncTask = null;
  120. this.play(args);
  121. } else {
  122. if (this._runningAsyncTask) {
  123. console.log(this._runningAsyncTask);
  124. }
  125. }
  126. }
  127. /**
  128. * 跳过当前正在执行的任务
  129. */
  130. step() {
  131. (this.isProcessing) && this._next_task(this._isProcessingTaskUUID);
  132. }
  133. /**
  134. * 开始运行队列
  135. */
  136. play(args: any = null) {
  137. if (this.isProcessing || !this._enable) {
  138. return;
  139. }
  140. let actionData: AsyncTask = this._queues.shift()!;
  141. if (actionData) {
  142. this._runningAsyncTask = actionData;
  143. let taskUUID: number = actionData.uuid;
  144. this._isProcessingTaskUUID = taskUUID;
  145. let callbacks: Array<AsyncCallback> = actionData.callbacks;
  146. if (callbacks.length == 1) {
  147. let nextFunc: NextFunction = (nextArgs: any = null) => {
  148. this._next_task(taskUUID, nextArgs);
  149. }
  150. callbacks[0](nextFunc, actionData.params, args);
  151. } else {
  152. // 多个任务函数同时执行
  153. let fnum: number = callbacks.length;
  154. let nextArgsArr: any[] = [];
  155. let nextFunc: NextFunction = (nextArgs: any = null) => {
  156. --fnum;
  157. nextArgsArr.push(nextArgs || null);
  158. if (fnum === 0) {
  159. this._next_task(taskUUID, nextArgsArr);
  160. }
  161. }
  162. let knum = fnum;
  163. for (let i = 0; i < knum; ++i) {
  164. callbacks[i](nextFunc, actionData.params, args);
  165. }
  166. }
  167. } else {
  168. this._isProcessingTaskUUID = 0;
  169. this._runningAsyncTask = null;
  170. (this.complete) && this.complete(args);
  171. }
  172. }
  173. /**
  174. * 往队列中push一个延时任务
  175. * @param time 时间(秒)
  176. * @param callback 时间到了之后回调
  177. */
  178. yieldTime(time: number, callback: Function = null) {
  179. let task = function (next: Function, params: any, args: any) {
  180. Framework.time.scheduleOnce(() => {
  181. callback && callback();
  182. next(args);
  183. }, time);
  184. }
  185. this.push(task, { des: "AsyncQueue.yieldTime" });
  186. }
  187. /**
  188. * 返回一个执行函数,执行函数调用count次后,next将触发
  189. * @param count
  190. * @param next
  191. * @return 返回一个匿名函数
  192. */
  193. static excuteTimes(count: number, next: Function = null) {
  194. let fnum: number = count;
  195. let tempCall = () => {
  196. --fnum;
  197. if (fnum === 0) {
  198. next && next();
  199. }
  200. }
  201. return tempCall;
  202. }
  203. }
  204. /**
  205. * let queue: AsyncQueue = new AsyncQueue();
  206. * //添加一个异步任务
  207. * queue.push(async (next: NextFunction, params: any, args: any) => {
  208. * load("",type,(error,res)=>{
  209. * next && next();
  210. * });
  211. * });
  212. *
  213. * //任务完成后的回调函数
  214. * queue.complete = () => {
  215. *
  216. * }
  217. *
  218. * //执行异步任务
  219. * queue.play();
  220. */