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

task-handler

v2.12.0

Published

Handle Javascript Timers like a boss! https://odo-network.github.io/task-handler/

Downloads

22

Readme

task-handler

npm Build Status Known Vulnerabilities Coverage Status Flow Coverage license

A simple, dependency-free task scheduling manager that makes it easy to handle tasks like a boss.

Install

yarn add task-handler

or

npm install --save task-handler

Coverage

Flow

This project provides .flow.js files for Flow to utilize. It also attempts to provide near-100% test coverage.

Typescript

This project provides the appropriate index.d.ts file for TypeScript users.

Example

Simple

/* @flow */

import createTaskHandler from "task-handler";

const task = createTaskHandler("simple");

// after timeout
const refOne = task.after("task:one", 3000, () => log("task:one execute"));

// every interval, execute
const refTwo = task.every("task:two", 3000, () => log("task:two execute"));

// immediately execute on next tick (nextTick, immediate, timeout priority - first found)
const refThree = task.defer("task:three", () => log("task:three execute"));

// every interval and immediately (defer), execute
const refFour = task.everyNow("task:four", 3000, () =>
  log("task:four execute")
);

// sequentially execute at an interval -
// waits until the function requested to
// finish before scheduling the next
// timeout.
// - NOTE: Awaits promises if returned
//         by the function. Which is not
//         the standard behavior.
const refFive = task.everySequential("task:five", 100, async () => {
  log("task:five execute");
  await new Promise(resolve => setTimeout(resolve, 3000));
  log("task:five completes");
});

// same as above but adds a deferred execution first
// which occurs on the next tick.
const refSix = task.everyNowSequential("task:six", 100, async () => {
  log("task:six execute");
  await new Promise(resolve => setTimeout(resolve, 3000));
  log("task:six completes");
});

// schedule an advanced async job with cancellation
const refSeven = task.job(
  "task:seven",
  function TaskFiveHandler(...args) {
    // args resolves to [ref, 1, 2, 3]
    // saved context - `this` resolves to the job `ref`
    const ref = this;
    return {
      async start(ref2) {
        // called when the job starts (synchronously)
        //
        // ref is also the first argument given, it is the same as the
        // top level `this` but can be used when using arrow function
        // at the top level.
        // ref.resolve('value');
        // ref.reject('error');
        // ref.cancel();
      },
      async cancelled() {
        // called if the job is cancelled
      },
      async complete() {
        // called when the job is complete (resolved, cancelled, or errored).
      }
    };
  },
  [1, 2, 3]
);

// get the total # of tasks scheduled
task.size; // 7

// cancels each of the given ID's, if they exist
task.cancel("task:one", "task:two");

// clear all tasks, killing the event queue and completing execution
task.after("complete", 10000, () => {
  log("complete - clearing tasks");
  task.clear();
});

Features / Summaries

Auto Cancellation

Creating a task with the same id as another task will cancel the previous task and schedule the next automatically.

Refs

task-handler implements a concept of task refs so that we can provide a unified API across all of the event types.

When using promises, the promise will be resolved with the ref for the task which allows capturing the result via ref.result.

If an error is caught, the error object will include the ref as a property.

export type Task$Types = "after" | "every" | "defer" | "job";

export type Task$Ref = {|
  /* Task ID */
  +id: any,
  /* indicates the general type of the task */
  +type: Task$Types,
  /* the result of executing the tasks handler */
  get result(): any,
  /* returns a promise that resolves to the next result.
     if the task is an 'every' type, it must be called 
     after every execution to continually get the next 
     promise (or use ref.promises() instead). */
  get promise(): () => Task$Promise$Regular,
  /* async iterator that provides results for each iteration.  May only be called on 'every' type tasks. */
  get promises(): () => Task$Promise$Every,
  /* Status about the task */
  +status: {
    /* Task is resolving by calling its execute handler */
    resolving: boolean,
    /* Task has resolved and has completed execution */
    complete: boolean,
    /* Task was cancelled */
    cancelled: boolean,
    /* Task encountered an error */
    error: boolean
  },
  /* Cancels the task, an alias for `task.cancel(ref.id)` */
  cancel(): void,
  /* Resolves the task with the value provided. */
  resolve(value: any): void,
  /* Rejects the event and calls the error handling 
     that is present on the task (if any).  Generally 
     used for `task.job` but works with any active 
     task. */
  reject(reason: any): void,
  /* top-level task handler the ref belongs to */
  task: Task$Handler
|};

For the complete types, view types.js.

Promises

When calling .promise() on the task ref, after and defer return regular promises that resolve to the task ref with a result of the function passed. If no function is passed then the ref.result will be undefined.

task
  .after("afterID", 1000, () => 1)
  .promise()
  .then(ref => {
    console.log("After 1000ms: ", ref.result); // After 1000ms: 1
  });

Interval tasks such as every and everyNow return async iterators when their .promises() function is called. This allows us to utilize the handy for await... of feature of JS.

IMPORTANT: Notice that every, everySequential, and their related siblings use .promises() and .promise(). If other functions call .promises() which are not interval types they will throw an error.

async function intervalForAwait() {
  const ref = task.every("everyID", 1000);
  for await (const ref of ref.promises()) {
    console.log("Next Tick");
    // based on some logic...
    ref.cancel();
  }
  console.log("After Cancel everyID");
}

// Or using standard async function...
async function intervalAwait() {
  const iter = task.every("everyID", 1000).promises();
  let done = false;
  let ref;
  while (!done) {
    let ref;
    ({ value: ref, done } = await iter.next());
    console.log("Next Tick");
    // based on some logic...
    ref.cancel();
  }
  console.log("After Cancel everyID");
}

// if we want to handle errors that are not caught
// in the task runner we can utilize a while loop:
async function awaitResults(ref) {
  const ref = task.every(
    "everyID",
    1000,
    () => throw new Error("Error Message")
  );
  while (true) {
    try {
      for await (const result of ref.promises()) {
        console.log("Tick!");
      }
      return;
    } catch (e) {
      console.log("Error!", e);
    }
  }
}