86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
/*
|
|
* https://github.com/morethanwords/tweb
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
*/
|
|
|
|
import { CancellablePromise, deferredPromise } from "./cancellablePromise";
|
|
import { getHeavyAnimationPromise } from "../hooks/useHeavyAnimationCheck";
|
|
import { fastRaf } from "./schedulers";
|
|
|
|
type HeavyQueue<T> = {
|
|
items: any[],
|
|
process: (...args: any[]) => T,
|
|
context: any,
|
|
promise?: CancellablePromise<ReturnType<HeavyQueue<T>['process']>[]>
|
|
};
|
|
const heavyQueue: HeavyQueue<any>[] = [];
|
|
let processingQueue = false;
|
|
|
|
export default function addHeavyTask<T>(queue: HeavyQueue<T>, method: 'push' | 'unshift' = 'push') {
|
|
if(!queue.items.length) {
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
queue.promise = deferredPromise<T[]>();
|
|
heavyQueue[method](queue);
|
|
processHeavyQueue();
|
|
|
|
return queue.promise;
|
|
}
|
|
|
|
function processHeavyQueue() {
|
|
if(!processingQueue) {
|
|
const queue = heavyQueue.shift();
|
|
timedChunk(queue).finally(() => {
|
|
processingQueue = false;
|
|
if(heavyQueue.length) {
|
|
processHeavyQueue();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function timedChunk<T>(queue: HeavyQueue<T>) {
|
|
if(!queue.items.length) {
|
|
queue.promise.resolve([]);
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
const todo = queue.items.slice();
|
|
const results: T[] = [];
|
|
|
|
return new Promise<T[]>((resolve, reject) => {
|
|
const f = async() => {
|
|
const start = performance.now();
|
|
|
|
do {
|
|
await getHeavyAnimationPromise();
|
|
const possiblePromise = queue.process.apply(queue.context, todo.shift());
|
|
let realResult: T;
|
|
if(possiblePromise instanceof Promise) {
|
|
try {
|
|
realResult = await possiblePromise;
|
|
} catch(err) {
|
|
reject(err);
|
|
return;
|
|
}
|
|
} else {
|
|
realResult = possiblePromise;
|
|
}
|
|
|
|
results.push(realResult);
|
|
} while(todo.length > 0 && (performance.now() - start) < 6);
|
|
|
|
if(todo.length > 0) {
|
|
fastRaf(f);
|
|
//setTimeout(f, 25);
|
|
} else {
|
|
resolve(results);
|
|
}
|
|
};
|
|
|
|
fastRaf(f);
|
|
//setTimeout(f, 25);
|
|
}).then(queue.promise.resolve, queue.promise.reject);
|
|
} |