npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@figliolia/task-queue

v1.0.7

Published

A lightweight task queue for managing prioritized and scheduled tasks

Downloads

13

Readme

Task Queue

Task prioritization and scheduling made easy!

Getting Started

Installation

npm install --save @figliolia/task-queue
# or
yarn add @figliolia/task-queue

Basic Usage

Scheduling Tasks using Prioritized Execution

import { TaskQueue } from "@figliolia/task-queue";

const TQ = new TaskQueue({ priorities: 4 });
// This TaskQueue will have 4 priority levels for
// registering tasks

const task1 = () => {};
const task2 = () => {};
const task3 = () => {};
const task4 = () => {};

TQ.registerTask(task1, 4); // Priority 4
TQ.registerTask(task2, 3); // Priority 3
TQ.registerTask(task3, 2); // Priority 2
TQ.registerTask(task4, 1); // Priority 1

const cancelFN = TQ.executeAll();
// The execution order => task4, task3, task2, task1

// Calling cancelFN() will cancel task execution at any point

Scheduling Tasks using deferrals

import { TaskQueue } from "@figliolia/task-queue";

const TQ = new TaskQueue();

const cancelFN = TQ.deferTask(() => {
  // This task will execute after 1000ms
  // and won't leak memory if canceled
}, 1000);

// Optionally calling `cancelFN()` will prevent the
// task from being executed

API

Task Queue

constructor(options): TaskQueue

The constructor can accept an options argument with the following keys and default values

const TQ = new TaskQueue({
  // The number of priority-levels your queue will have
  priorities: 1,
  // Whether or not your queue will auto-run tasks as they're added
  // to the queue
  autoRun: false,
  // The number of milliseconds to elapse between tasks. For all 
  // TaskQueue methods that accept a taskSeparation argument its 
  // value defaults to the one provided by this parameter
  taskSeparation: 0,
  // When using this module in the browser and user-interaction 
  // is detected, this argument represents the number of 
  // milliseconds to pause the tasks queue and yield to the main 
  // thread
  mainThreadYieldTime: 5,
})

registerTask(task: Task, priority: number): CancelFN

Registers a function to execute at a certain priority level. Returns a cancel function that, if called, will remove the task from the queue

import { TaskQueue } from "@figliolia/task-queue";

const N = 3;

const TQ = TaskQueue({ priorities: N });

const cancelFN = TQ.registerTask(() => {}, 1)

deferTask(task: Task, delay: number): CancelFN

Registers a task to execute after a specified delay. Returns a cancel function that, if called, will remove the task from the queue

import { TaskQueue } from "@figliolia/task-queue";

const TQ = TaskQueue();

const cancelFN = TQ.deferTask(() => {}, 1000);

executeAll(onComplete?: Task, taskSeparation?: number): CancelFN

Executes all prioritized tasks registered using registerTask(). Tasks are executed based on the priority levels that they were registered with and dispersed along the call stack using the taskSeparation.

import { TaskQueue } from "@figliolia/task-queue";

const TQ = TaskQueue({ priorities: 3 });

// Register any number of tasks
TQ.registerTask(() => {}, 1);
TQ.registerTask(() => {}, 2);
TQ.registerTask(() => {}, 3);

const cancelFN = TQ.executeAll(() => {
  console.log('Complete!');
}, 35 /* task separation */);

The taskSeparation parameter can be used to disperse registered tasks along the call stack. taskSeparation = the number of milliseconds to elapse between tasks. It's set to 0 by default. This is designed to prevent the creation of long blocking tasks when the Task Queue has several entries.

Invoking the returned cancel function will pause the execution of the remaining tasks in the queue until executeAll() is called again.

executeTasksWithPriority(): CancelFN

Executes all tasks registered at a specified priority level. Returns a cancel function

import { TaskQueue } from "@figliolia/task-queue";

const TQ = TaskQueue({ priorities: 3 });
// Register any number of tasks

const cancelFN = TQ.executeTasksWithPriority(
  1, // Priority 
  0, // Task Separation MS
  () => { // On complete function
  console.log("Complete!");
});
// Executes all tasks registered with priority level 1

Calling the returned cancel function will pause the execution of tasks.

Using executeTasksWithPriority() can allow developers to organize tasks based on arbitrary means and identify them using their priority. This can be useful if managing the execution of registered tasks based on arbitrary categorization. Let's look at an example using application routing:

import { TaskQueue } from "@figliolia/task-queue";

const TQ = new TaskQueue({ priorities: 3 });

// Let's map our application routes to a priority level
enum RouteMap {
  "home" = 1,
  "about" = 2,
  "profile" = 3
}

// Next lets register a data loading task for
// each route
TQ.registerTask(() => {
  // Tasks to execute when navigating to home
  void fetchGreeting();
}, RouteMap.home);

TQ.registerTask(() => {
  // Tasks to execute when navigating to about
  void fetchUserData();
}, RouteMap.about);

TQ.registerTask(() => {
  // Tasks to execute when navigating to profile
  void fetchProfile();
}, RouteMap.profile);

// Listen for routing changes using hashchange or pushstate
window.addEventListener("hashchange", () => {
  const nextRoute = window.location.hash.slice(1);
  if(nextRoute in RouteMap) {
    // Execute data loader for matched routes!
    TQ.executeTasksWithPriority(routeMap[nextRoute]);
  }
});

In the above example, the TaskQueue's priority levels are used for categorizing data preloading tasks based on the route they correspond with. When the browser routes to a supported route found in the routeMap, the tasks corresponding with the route are executed as early as possible.

clearPendingTasks(): void

Removes all pending tasks from the task TaskQueue. This includes both prioritized tasks registered using TaskQueue.registerTask() and deferred tasks registered using TaskQueue.deferTask()

import { TaskQueue } from "@figliolia/task-queue";

const TQ = TaskQueue({ priorities: 3 });

TQ.registerTask(() => {}, 1);
TQ.registerTask(() => {}, 2);
TQ.registerTask(() => {}, 3);
TQ.deferTask(() => {}, 1000);

TQ.clearPendingTasks(); 
// Resets the Queue removing all registered tasks

clearDeferredTasks(): void

Removes all pending tasks registered using TaskQueue.deferTask(). These tasks are released, cancelled and forgotten by the TaskQueue

import { TaskQueue } from "@figliolia/task-queue";

const TQ = TaskQueue();

TQ.deferTask(() => {}, 1000);
TQ.deferTask(() => {}, 2000);
TQ.deferTask(() => {}, 3000);

TQ.clearDeferredTasks(); 
// Cancels all currently pending deferred tasks

getCancelFN(): CancelFN | void

Returns the current cancel token if the TaskQueue is executing or undefined if the TaskQueue is idol.

import { TaskQueue } from "@figliolia/task-queue";

const TQ = TaskQueue({ priorities: 3 });

// Register any number of tasks
TQ.registerTask(() => {}, 1);
TQ.registerTask(() => {}, 2);
TQ.registerTask(() => {}, 3);

TQ.executeAll();

const cancel = TQ.getCancelFN(); 
// Returns a CancelFN during execution
cancel && cancel()

Advanced Usage

Using autoRun

The autoRun option is designed to make your TaskQueues run at all times. This option will cause registered tasks to auto-execute as soon as they're enqueued. Tasks will continue to execute at their appropriate priority levels, but allow lower priority tasks to execute immediately if the Queue is empty!

const TQ = new TaskQueue({ 
  priorities: 3, 
  autoRun: true,
  taskSeparation: 10,
  mainThreadYieldTime: 5,
});

const task1 = () => {};
const task2 = () => {};
const task3 = () => {}

TQ.registerTask(task3, 3);
TQ.registerTask(task2, 2);
TQ.registerTask(task1, 1);

// The above tasks will execute without calling `TQ.executeAll()`

// The execution order will be task1 => task2 => task3 with 10ms 
// elapsing between each task

// To cancel task execution at any point
const cancel = TQ.getCancelFN();
cancel && cancel();

// To begin execution again
TQ.executeAll()

Using the autoRun option is great prioritizing the execution of startup tasks in complex frontend apps or responsibly managing request handling on the server