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 🙏

© 2025 – Pkg Stats / Ryan Hefner

use-tasker

v0.0.5

Published

A hooks based asynchronous task runner for react

Downloads

21

Readme

useTasker

A React Hook to schedule asynchronous things.

Install

yarn add use-tasker

Usage

Import the repo and try out the example in CodeSandbox:

https://codesandbox.io/s/github/boopathi/use-tasker

Example:

import { useTasker, seq, concurrent, task } from "use-tasker";

const sleep = (t) => new Promise((r) => setTimeout(r, t));

function Pipeline() {
  const { state, start } = useTasker(
    seq(
      "pipeline",
      task("title 1", async () => {
        await sleep(2000);
      }),
      concurrent(
        "deploy",
        task("deploy pods", async () => {
          await sleep(3000);
        }),
        task("deploy service", async () => {
          await sleep(3000);
        }),
        task("deploy ingress", async () => {
          await sleep(3000);
        })
      )
    )
  );

  return (
    <div>
      <pre>
        <code>{JSON.stringify(state, null, 2)}</code>
      </pre>
    </div>
  );
}

API

useTasker

const { state, start } = useTasker(taskList, context);
  • taskList: TaskList - The TaskList returned by seq or concurrent functions described below
  • context: any - The parameter passed to all taskFn functions. You can use this as an internal state to pass values from one task to another.
  • returns { state, start }
  • state: TaskerState - A nested structure that is updated as the tasks complete. This is the store of a reducer. More details under state topic.
  • start: () => void - The function to start running the tasks. Add this as the click event handler of a button or a similar other thing.

state

The state returned by the useTasker hook gives the current state of the execution pipeline. It's a nested recursive structure that is derived from the input structure of the taskList.

The type definition of the state can be imported for TS projects and is defined as -

type TaskRunStatus = "NOT_STARTED" | "LOADING" | "SUCCESS" | "ERROR";

interface TaskerState {
  title: string;
  status: TaskRunStatus;
  tasks?: TaskerState[];
  error?: any;
}

The state updates as and when the execution proceeds and triggers a re-render of the component that uses useTasker. You can create two mututally recursive components to render this recursive state. For example, the following code will render the recursive state as a nested ul, li list.

import { TaskerState } from "use-tasker";

function ListItem({ data }: { data: TaskerState }) {
  return (
    <li>
      {data.status}: {data.title} ({data.error ? data.error.message : null})
      {data.tasks ? <List tasks={data.tasks} /> : null}
    </li>
  );
}

function List({ tasks }: { tasks: TaskerState["tasks"] }) {
  return (
    <ul>
      {tasks.map((it) => (
        <ListItem data={it} key={it.title + it.status} />
      ))}
    </ul>
  );
}

task

import { task } from "use-tasker";

The task specifier. A task can retur any value including promises. If a task returns, it means it is successfully completed. If the task throws an error or returns a rejected promise, the task failed.

task(name, taskFn);
  • name: string- name of the task
  • taskFn: (context) => any | Promise<any> - the task function
    • context: any - the context passed to useTasker
  • returns Task

seq

import { seq } from "use-tasker";

A sequence TaskList specifier. Members of the sequence are executed sequentially. An Error in one of the steps will stop the execution of the sequence.

seq(name, ...taskLike);
  • name: string- name for the sequence
  • taskLike: Task | TaskList - a Task returned by the task function or another seq or concurrent TaskList returned by seq or concurrent functions
  • returns TaskList

concurrent

import { concurrent } from "use-tasker";

A concurrent TaskList specifier. Members are executed concurrently using Promise.allSettled. An error in one or more of the members will be collected and thrown as a ConcurrentTasksError - more details about this error is described below in Error Handling.

concurrent(name, ...taskLike);
  • name: string- name for the concurrent tasks
  • taskLike: Task | TaskList - a Task returned by the task function or another seq or concurrent TaskList returned by seq or concurrent functions
  • returns TaskList

Error handling

  • task: Tasks can throw an error or return a rejected Promise. Depending on whether it is used as a member of seq or concurrent, the error is handled accordingly.

    task("title1", () => {
      throw new Error("title1");
    });
    task("title2", () => {
      return Promise.reject(new Error("title2"));
    });
  • seq: Errors thrown or rejected promises in seq stop the current pipeline.

  • concurrent: Errors thrown or rejected promises in concurrent are collected as it is collected by Promise.allSettled. They are then wrapped using a custom error class - ConcurrentTasksError. For example,

    import { ConcurrentTasksError } from "use-tasker";
    
    function ErrorComponent(state: TaskerState) {
      if (state.error) {
        if (state.error instanceof ConcurrentTasksError) {
          return <div>{state.error.errors.map((err) => err.message)}</div>;
        }
      }
      return null;
    }

Related

This project is inspired by Listr, which is a terminal task list.

License

MIT