Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

async-task-schedule

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

async-task-schedule - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

134

dist/index.es.js

@@ -24,3 +24,2 @@ function $parcel$export(e, n, v, s) {

this.pendingTasks = [];
this.doingTasks = [];
this.doneTaskMap = [];

@@ -33,7 +32,9 @@ this.taskQueue = [];

if (!userOptions.batchDoTasks && !userOptions.doTask) throw new Error("one of batchDoTasks / doTask must be specified");
this.batchDoTasks = userOptions.batchDoTasks || $d415641d0cfd8c85$export$37f92047f3e3e1d6.wrapDoTask(userOptions.doTask);
this.doTask = userOptions.doTask;
this.batchDoTasks = userOptions.batchDoTasks;
this.taskExecStrategy = userOptions.taskExecStrategy;
if (this.taskExecStrategy === "serial") this.maxBatchCount = 1;
this.retryWhenFailed = userOptions.retryWhenFailed;
this.invalidAfter = userOptions.invalidAfter;
this.tryTodDoTasks = this.tryTodDoTasks.bind(this);
this.runTasks = this.runTasks.bind(this);
this.dispatch = this.dispatch.bind(this);

@@ -48,3 +49,3 @@ }

} catch (error) {
// not found
// note all tasks are cached, just created new tasks
}

@@ -57,3 +58,4 @@ return new Promise((resolve, reject)=>{

* clean cached task result
* this may not exec immediately, it will take effect after all tasks are done
* - this may not exec immediately
* - it will take effect after all tasks are done
*/ cleanCache() {

@@ -67,3 +69,3 @@ this.needCleanCache = true;

if (!this.needCleanCache) return;
if (this.pendingTasks.length || this.doingTasks.length || this.taskQueue.length) return;
if (this.pendingTasks.length || this.taskQueue.length) return;
this.needCleanCache = false;

@@ -90,4 +92,2 @@ this.doneTaskMap = [];

if (this.pendingTasks.length) myTasks = myTasks.filter((f)=>!this.hasTask(this.pendingTasks, f));
// remove doing tasks
if (myTasks.length && this.doingTasks.length) myTasks = myTasks.filter((f)=>!this.hasTask(this.doingTasks, f));
// remove done tasks

@@ -104,44 +104,49 @@ if (myTasks.length) myTasks = myTasks.filter((f)=>!this.getTaskResult(f));

} else timeout = this.maxWaitingGap;
this.timeoutId = setTimeout(this.tryTodDoTasks, timeout);
this.timeoutId = setTimeout(this.runTasks, timeout);
}
/**
* try to do tasks
* if taskExecStrategy is parallel then do it immediately,
* otherwise waiting util doingTasks is empty
*/ tryTodDoTasks() {
// should exec in serial, and still has executing tasks
if (this.taskExecStrategy === "serial" && this.doingTasks.length) {
clearTimeout(this.delayTimeoutId);
// wait a moment then check again
this.delayTimeoutId = setTimeout(this.tryTodDoTasks, 50);
} else this.doTasks();
// whether task is running
isTaskRunning = false;
runTasks() {
if (this.isTaskRunning || !this.pendingTasks.length) return;
this.isTaskRunning = true;
if (this.batchDoTasks) this.runTaskWithBatchDoTasks();
else this.runTasksWithDoTask();
}
async doTasks() {
const tasks = this.pendingTasks.splice(0);
this.doingTasks = this.doingTasks.concat(tasks);
const tasksGroup = this.maxBatchCount ? $d415641d0cfd8c85$export$37f92047f3e3e1d6.chunk(tasks, this.maxBatchCount) : [
tasks
];
if (this.taskExecStrategy === "serial") // eslint-disable-next-line no-plusplus
for(let index = 0; index < tasksGroup.length; ++index){
const taskList = tasksGroup[index];
async runTasksWithDoTask() {
const taskItems = this.pendingTasks.splice(0, this.maxBatchCount || this.pendingTasks.length);
taskItems.forEach(async (task)=>{
try {
// eslint-disable-next-line no-await-in-loop
const result = await this.batchDoTasks(taskList);
this.updateResultMap(taskList, result);
const result = await this.doTask(task);
this.updateResultMap([
task
], [
result
]);
} catch (error) {
this.updateResultMap(taskList, $d415641d0cfd8c85$export$37f92047f3e3e1d6.wrapError(error));
this.updateResultMap([
task
], $d415641d0cfd8c85$export$37f92047f3e3e1d6.wrapError(error));
}
this.checkAllTasks();
this.removeDoneTasks(taskList);
if (this.pendingTasks.length) this.runTasksWithDoTask();
else {
this.cleanupTasks();
this.isTaskRunning = false;
}
});
}
async runTaskWithBatchDoTasks() {
const taskItems = this.pendingTasks.splice(0, this.maxBatchCount || this.pendingTasks.length);
try {
const result = await this.batchDoTasks(taskItems);
this.updateResultMap(taskItems, result);
} catch (error) {
this.updateResultMap(taskItems, $d415641d0cfd8c85$export$37f92047f3e3e1d6.wrapError(error));
}
this.checkAllTasks();
if (this.pendingTasks.length) this.runTaskWithBatchDoTasks();
else {
const allResponse = await Promise.all(tasksGroup.map((taskList)=>$d415641d0cfd8c85$export$37f92047f3e3e1d6.runTaskExecutor(this.batchDoTasks, taskList)));
allResponse.forEach((result, index)=>{
this.updateResultMap(tasksGroup[index], result.status === "rejected" ? $d415641d0cfd8c85$export$37f92047f3e3e1d6.wrapError(result.reason) : result.value);
});
this.checkAllTasks();
this.removeDoneTasks(tasks);
this.cleanupTasks();
this.isTaskRunning = false;
}
this.cleanupTasks();
}

@@ -176,3 +181,3 @@ /**

return tasks.reduce((acc, task)=>{
const val = this.getTaskResult(task) || false;
const val = this.getTaskResult(task);
if (!val) throw new Error("not found");

@@ -183,3 +188,3 @@ acc.push(val[1]);

}
const val = this.getTaskResult(tasks) || false;
const val = this.getTaskResult(tasks);
if (!val) throw new Error("not found");

@@ -198,5 +203,2 @@ return val[1];

}
removeDoneTasks(tasks) {
this.doingTasks = this.doingTasks.filter((f)=>!this.hasTask(tasks, f));
}
updateResultMap(tasks, result) {

@@ -216,3 +218,3 @@ const now = Date.now();

task: t,
value: taskResult ? taskResult : defaultValue,
value: taskResult,
time: now

@@ -226,4 +228,4 @@ };

* clean tasks
* try to clean cache if needed
* try to remove failed result, remove outdated cache if needed
* - try to clean cache if needed
* - try to remove failed result, remove outdated cache if needed
*/ cleanupTasks() {

@@ -233,2 +235,4 @@ this.cleanCacheIfNeeded();

if (this.taskQueue.length) return;
// nothing to cleanup
if (!this.doneTaskMap.length) return;
// no need to remove outdated or failed tasks

@@ -240,8 +244,5 @@ if (!this.invalidAfter && !this.retryWhenFailed) return;

if (this.invalidAfter) {
const time = typeof this.invalidAfter === "function" ? this.invalidAfter([
item.task,
item.value
]) : this.invalidAfter;
if (!time) return true;
return now - item.time <= this.invalidAfter;
const invalidAfter = typeof this.invalidAfter === "function" ? this.invalidAfter(item.task, item.value) : this.invalidAfter;
if (!invalidAfter) return true;
return now - item.time <= invalidAfter;
}

@@ -262,12 +263,2 @@ return true;

/**
* split array to chunks with specified size
* @param arr array of fileIds
* @param size chunk size
* @returns 2 dimensional array
*/ static chunk(arr, size) {
const result = [];
for(let i = 0; i < arr.length; i += size)result.push(arr.slice(i, i + size));
return result;
}
/**
* simulate Promise.allSettled result item for better compatibility

@@ -292,15 +283,2 @@ * (due to Promise.allSettled only support newer platforms)

/**
* wrap do task to a batch version
* @param doTask action to do single task
* @returns batch version to do multi tasks
*/ static wrapDoTask(doTask) {
return async function(tasks) {
const results = await Promise.all(tasks.map((t)=>$d415641d0cfd8c85$export$37f92047f3e3e1d6.runTaskExecutor(doTask, t)));
return tasks.map((t, idx)=>{
const result = results[idx];
return result.status === "fulfilled" ? result.value : result.reason;
});
};
}
/**
* check whether the given values are equal (with deep comparison)

@@ -307,0 +285,0 @@ */ static isEqual(a, b) {

@@ -23,3 +23,2 @@ function $parcel$export(e, n, v, s) {

this.pendingTasks = [];
this.doingTasks = [];
this.doneTaskMap = [];

@@ -32,7 +31,9 @@ this.taskQueue = [];

if (!userOptions.batchDoTasks && !userOptions.doTask) throw new Error("one of batchDoTasks / doTask must be specified");
this.batchDoTasks = userOptions.batchDoTasks || $f5bfd4ce37214f4f$export$37f92047f3e3e1d6.wrapDoTask(userOptions.doTask);
this.doTask = userOptions.doTask;
this.batchDoTasks = userOptions.batchDoTasks;
this.taskExecStrategy = userOptions.taskExecStrategy;
if (this.taskExecStrategy === "serial") this.maxBatchCount = 1;
this.retryWhenFailed = userOptions.retryWhenFailed;
this.invalidAfter = userOptions.invalidAfter;
this.tryTodDoTasks = this.tryTodDoTasks.bind(this);
this.runTasks = this.runTasks.bind(this);
this.dispatch = this.dispatch.bind(this);

@@ -47,3 +48,3 @@ }

} catch (error) {
// not found
// note all tasks are cached, just created new tasks
}

@@ -56,3 +57,4 @@ return new Promise((resolve, reject)=>{

* clean cached task result
* this may not exec immediately, it will take effect after all tasks are done
* - this may not exec immediately
* - it will take effect after all tasks are done
*/ cleanCache() {

@@ -66,3 +68,3 @@ this.needCleanCache = true;

if (!this.needCleanCache) return;
if (this.pendingTasks.length || this.doingTasks.length || this.taskQueue.length) return;
if (this.pendingTasks.length || this.taskQueue.length) return;
this.needCleanCache = false;

@@ -89,4 +91,2 @@ this.doneTaskMap = [];

if (this.pendingTasks.length) myTasks = myTasks.filter((f)=>!this.hasTask(this.pendingTasks, f));
// remove doing tasks
if (myTasks.length && this.doingTasks.length) myTasks = myTasks.filter((f)=>!this.hasTask(this.doingTasks, f));
// remove done tasks

@@ -103,44 +103,49 @@ if (myTasks.length) myTasks = myTasks.filter((f)=>!this.getTaskResult(f));

} else timeout = this.maxWaitingGap;
this.timeoutId = setTimeout(this.tryTodDoTasks, timeout);
this.timeoutId = setTimeout(this.runTasks, timeout);
}
/**
* try to do tasks
* if taskExecStrategy is parallel then do it immediately,
* otherwise waiting util doingTasks is empty
*/ tryTodDoTasks() {
// should exec in serial, and still has executing tasks
if (this.taskExecStrategy === "serial" && this.doingTasks.length) {
clearTimeout(this.delayTimeoutId);
// wait a moment then check again
this.delayTimeoutId = setTimeout(this.tryTodDoTasks, 50);
} else this.doTasks();
// whether task is running
isTaskRunning = false;
runTasks() {
if (this.isTaskRunning || !this.pendingTasks.length) return;
this.isTaskRunning = true;
if (this.batchDoTasks) this.runTaskWithBatchDoTasks();
else this.runTasksWithDoTask();
}
async doTasks() {
const tasks = this.pendingTasks.splice(0);
this.doingTasks = this.doingTasks.concat(tasks);
const tasksGroup = this.maxBatchCount ? $f5bfd4ce37214f4f$export$37f92047f3e3e1d6.chunk(tasks, this.maxBatchCount) : [
tasks
];
if (this.taskExecStrategy === "serial") // eslint-disable-next-line no-plusplus
for(let index = 0; index < tasksGroup.length; ++index){
const taskList = tasksGroup[index];
async runTasksWithDoTask() {
const taskItems = this.pendingTasks.splice(0, this.maxBatchCount || this.pendingTasks.length);
taskItems.forEach(async (task)=>{
try {
// eslint-disable-next-line no-await-in-loop
const result = await this.batchDoTasks(taskList);
this.updateResultMap(taskList, result);
const result = await this.doTask(task);
this.updateResultMap([
task
], [
result
]);
} catch (error) {
this.updateResultMap(taskList, $f5bfd4ce37214f4f$export$37f92047f3e3e1d6.wrapError(error));
this.updateResultMap([
task
], $f5bfd4ce37214f4f$export$37f92047f3e3e1d6.wrapError(error));
}
this.checkAllTasks();
this.removeDoneTasks(taskList);
if (this.pendingTasks.length) this.runTasksWithDoTask();
else {
this.cleanupTasks();
this.isTaskRunning = false;
}
});
}
async runTaskWithBatchDoTasks() {
const taskItems = this.pendingTasks.splice(0, this.maxBatchCount || this.pendingTasks.length);
try {
const result = await this.batchDoTasks(taskItems);
this.updateResultMap(taskItems, result);
} catch (error) {
this.updateResultMap(taskItems, $f5bfd4ce37214f4f$export$37f92047f3e3e1d6.wrapError(error));
}
this.checkAllTasks();
if (this.pendingTasks.length) this.runTaskWithBatchDoTasks();
else {
const allResponse = await Promise.all(tasksGroup.map((taskList)=>$f5bfd4ce37214f4f$export$37f92047f3e3e1d6.runTaskExecutor(this.batchDoTasks, taskList)));
allResponse.forEach((result, index)=>{
this.updateResultMap(tasksGroup[index], result.status === "rejected" ? $f5bfd4ce37214f4f$export$37f92047f3e3e1d6.wrapError(result.reason) : result.value);
});
this.checkAllTasks();
this.removeDoneTasks(tasks);
this.cleanupTasks();
this.isTaskRunning = false;
}
this.cleanupTasks();
}

@@ -175,3 +180,3 @@ /**

return tasks.reduce((acc, task)=>{
const val = this.getTaskResult(task) || false;
const val = this.getTaskResult(task);
if (!val) throw new Error("not found");

@@ -182,3 +187,3 @@ acc.push(val[1]);

}
const val = this.getTaskResult(tasks) || false;
const val = this.getTaskResult(tasks);
if (!val) throw new Error("not found");

@@ -197,5 +202,2 @@ return val[1];

}
removeDoneTasks(tasks) {
this.doingTasks = this.doingTasks.filter((f)=>!this.hasTask(tasks, f));
}
updateResultMap(tasks, result) {

@@ -215,3 +217,3 @@ const now = Date.now();

task: t,
value: taskResult ? taskResult : defaultValue,
value: taskResult,
time: now

@@ -225,4 +227,4 @@ };

* clean tasks
* try to clean cache if needed
* try to remove failed result, remove outdated cache if needed
* - try to clean cache if needed
* - try to remove failed result, remove outdated cache if needed
*/ cleanupTasks() {

@@ -232,2 +234,4 @@ this.cleanCacheIfNeeded();

if (this.taskQueue.length) return;
// nothing to cleanup
if (!this.doneTaskMap.length) return;
// no need to remove outdated or failed tasks

@@ -239,8 +243,5 @@ if (!this.invalidAfter && !this.retryWhenFailed) return;

if (this.invalidAfter) {
const time = typeof this.invalidAfter === "function" ? this.invalidAfter([
item.task,
item.value
]) : this.invalidAfter;
if (!time) return true;
return now - item.time <= this.invalidAfter;
const invalidAfter = typeof this.invalidAfter === "function" ? this.invalidAfter(item.task, item.value) : this.invalidAfter;
if (!invalidAfter) return true;
return now - item.time <= invalidAfter;
}

@@ -261,12 +262,2 @@ return true;

/**
* split array to chunks with specified size
* @param arr array of fileIds
* @param size chunk size
* @returns 2 dimensional array
*/ static chunk(arr, size) {
const result = [];
for(let i = 0; i < arr.length; i += size)result.push(arr.slice(i, i + size));
return result;
}
/**
* simulate Promise.allSettled result item for better compatibility

@@ -291,15 +282,2 @@ * (due to Promise.allSettled only support newer platforms)

/**
* wrap do task to a batch version
* @param doTask action to do single task
* @returns batch version to do multi tasks
*/ static wrapDoTask(doTask) {
return async function(tasks) {
const results = await Promise.all(tasks.map((t)=>$f5bfd4ce37214f4f$export$37f92047f3e3e1d6.runTaskExecutor(doTask, t)));
return tasks.map((t, idx)=>{
const result = results[idx];
return result.status === "fulfilled" ? result.value : result.reason;
});
};
}
/**
* check whether the given values are equal (with deep comparison)

@@ -306,0 +284,0 @@ */ static isEqual(a, b) {

@@ -35,3 +35,3 @@ export type ITaskExecStrategy = 'parallel' | 'serial';

*/
invalidAfter?: number | ((cached: readonly [Task, Result | Error]) => number);
invalidAfter?: number | ((task: Task, result: Result | Error) => number);
/**

@@ -42,3 +42,3 @@ * retry failed tasks next time after failing, default true

/**
* task waiting stragy, default to debounce
* task waiting strategy, default to debounce
* throttle: tasks will combined and dispatch every `maxWaitingGap`

@@ -65,5 +65,7 @@ * debounce: tasks will combined and dispatch util no more tasks in next `maxWaitingGap`

* clean cached task result
* this may not exec immediately, it will take effect after all tasks are done
* - this may not exec immediately
* - it will take effect after all tasks are done
*/
cleanCache(): void;
isTaskRunning: boolean;
/**

@@ -75,9 +77,2 @@ * wrap error info, if it's not instanceof Error, wrap it with Error

/**
* split array to chunks with specified size
* @param arr array of fileIds
* @param size chunk size
* @returns 2 dimensional array
*/
static chunk<T>(arr: T[], size: number): T[][];
/**
* simulate Promise.allSettled result item for better compatibility

@@ -96,8 +91,2 @@ * (due to Promise.allSettled only support newer platforms)

/**
* wrap do task to a batch version
* @param doTask action to do single task
* @returns batch version to do multi tasks
*/
static wrapDoTask<T, R>(doTask: (t: T) => Promise<R> | R): (tasks: T[]) => Promise<Array<R | Error>>;
/**
* check whether the given values are equal (with deep comparison)

@@ -104,0 +93,0 @@ */

{
"name": "async-task-schedule",
"version": "1.0.0",
"version": "1.0.1",
"description": "schedule async tasks",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -142,3 +142,3 @@ # async-task-schedule

*/
invalidAfter?: number | ((cached: readonly [Task, Result | Error]) => number)
invalidAfter?: number | ((task: Task, result: Result | Error) => number)

@@ -262,12 +262,3 @@ /**

### chunk<T>(arr: T[], size: number): T[][]
split array to chunks with specified size
```ts
import TaskSchedule from 'async-task-schedule'
const chunked = TaskSchedule.chunk([1,2,3,4,5,6,7], 3)
// [[1,2,3], [4,5,6], [7]]
```
### isEqual(a: unknown, b: unknown): boolean

@@ -305,3 +296,3 @@ check whether the given values are equal (with deep comparison)

// set a minimum number 1 can disable cache after 1 millisecond
invalidAfter([cfg, result]) {
invalidAfter(cfg, result) {
// cache get request for 3s

@@ -334,2 +325,3 @@ if (!cfg.options || !cfg.options.method || !cfg.options.method.toLowerCase() === 'get') {

```ts
// support max 5 users at a time
getUsers(userIds: string[]) => Promise<[{code: string, message: string, id?: string, name?: string, email?: string}]>

@@ -348,2 +340,3 @@ ```

const getUserSchedule = new TaskSchedule({
maxBatchCount: 5,
batchDoTasks: batchGetUsers,

@@ -355,6 +348,8 @@ // cache user info forever

const result = await Promise.all([
getUserSchedule.dispatch(['user1', 'user2']),
getUserSchedule.dispatch(['user1', 'user2', 'user3', 'user4', 'user5', 'user6']),
getUserSchedule.dispatch(['user3', 'user2'])
getUserSchedule.dispatch(['user6', 'user7', 'user8', 'user9', 'user10'])
getUserSchedule.dispatch(['user2', 'user6', 'user9'])
])
// only one request will be sent via getUsers with userIds ['user1', 'user2', 'user3']
// only 2 requests will be sent via getUsers with userIds ['user1', 'user2', 'user3', 'user4', 'user5'] and ['user6', 'user7', 'user8', 'user9', 'user10']

@@ -361,0 +356,0 @@ // request combine won't works when using await separately

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc