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-async-loop

v1.0.2

Published

Asynchronously iterate a single task (sync/async/promises) with delay after each task execution and dynamic loop exit conditions.

Downloads

3

Readme

Task async Loop

Task Async Loop is a Node.js module that allows you to run sequentially, in an asynchronous loop, any synchronous/asynchronous/promise based task.

  • Each loop execution starts when the previous execution stops in a strict sequence.

  • An optional delay can be specified to sleep at the end of each iteration (e.g., for polling tasks).

  • An exit loop condition function can be provided.

  • Loop can be dynamically interrupted during the execution task.

  • Sleep time after each iteration can be changed dynamically during task execution.

Installation

npm install task-async-loop

Dependencies

None.

Usage

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop(options);

where options is an object having the following properties:

  • delay: delay between each loop, in milliseconds. The first loop has no initial delay.
  • data: a shared object between condition and executer (see below).
  • condition(data): an optional function returning a boolean value:
    • true to keep executing the task (default value if condition is not defined, therefore looping forever).
    • false to stop iterations.
  • executer(data, next, stop. setDelay): an optional function executing a task. If not specified, no action is executed.
    • data: the shared object
    • next: must to be called when the task ends, to get to the next iteration.
    • stop: must be called to stop the iteration loop.
    • setDelay: can be invoked to set a new delay dynamically.

Examples

Loop a synchronous task #1

Logs every second, forever.

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 1000,
    executer: (data, next, stop, setDelay) => {
        console.log("loop");

        next(); // continue iteration
    }
});

Loop a synchronous task #2

Logs every second, 10 times.

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 1000,
    data: {
        count: 0
    },
    condition: (data) => {
        return data.count++ < 10;
    },
    executer: (data, next, stop, setDelay) => {
        console.log(`loop #${data.count}`);

        next(); // continue iteration
    }
});

Loop a synchronous task #3

Dynamic loop exit condition

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 1000,
    executer: (data, next, stop, setDelay) => {
        const time = new Date().getTime();
        console.log(`loop at ${time}`);

        // simulate exit condition
        if (time % 4 !== 0) {
            next(); // continue iteration
        } else {
            stop(); // exit iteration
        }
    }
});

Loop an asynchronous task #1

Run an async call, sleeping 2 seconds after each execution

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 2000,
    executer: (data, next, stop, setDelay) => {
        setTimeout(() => {
            console.log(`loop at ${new Date().getTime()}`);
            next();
        }, Math.floor(Math.random() * 3000)); // simulate execution time
    }
});

Loop an asynchronous task #2

Dynamic loop exit condition

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 2000,
    executer: (data, next, stop, setDelay) => {
        setTimeout(() => {
            const time = new Date().getTime();
            console.log(`loop at ${time}`);

            // simulate exit condition
            if (time % 4 != 0) {
                next(); // continue iteration
            } else {
                stop(); // exit iteration
            }
        }, Math.floor(Math.random() * 1000)); // simulate execution time
    }
});

Loop an asynchronous task #3

Dynamic sleep after each iteration

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    executer: (data, next, stop, setDelay) => {
        setTimeout(() => {
            console.log(`loop at ${new Date().getTime()}`);

            // change loop delay for the next iteration
            setDelay(Math.floor(Math.random() * 5000));

            next(); // continue iteration
        }, Math.floor(Math.random() * 1000)); // simulate execution time
    }
});

Loop an asynchronous task #4

Error management. Stop iterations upon unexpected error

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 2000,
    executer: (data, next, stop, setDelay) => {
        setTimeout(() => {
            const time = new Date().getTime();
            console.log(`loop at ${time}`);

            try {
                // generate random error
                if (time % 4 != 0) {
                    next(); // continue iteration
                } else {
                    throw new Error();
                }
            } catch {
                stop(); // manage unexpected error exiting loop
            }
        }, Math.floor(Math.random() * 1000)); // simulate execution time
    }
});

Loop a Promise #1

Run promise 10 times, sleeping 1 second after each execution

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 1000,
    data: {
        count: 0
    },
    condition: (data) => {
        return data.count++ < 10;
    },
    executer: (data, next, stop, setDelay) => {
        new Promise((resolve, reject) => {
            console.log(`looping with count ${data.count}`);
            resolve();
        }).then(() => {
            next();
        });
    }
});

Loop a Promise #2

Run promise, with 1 second delay, exit on dynamic condition

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 1000,
    data: {
        count: 0
    },
    executer: (data, next, stop, setDelay) => {
        new Promise((resolve, reject) => {
            data.count++;
            console.log(`looping with count ${data.count}`);

            if (data.count >= 5) {
                reject(); // or throw new Error()
            } else {
                resolve();
            }
        })
            .then(() => {
                next();
            })
            .catch(() => {
                stop();
            });
    }
});

HTTP Request Polling

Loop over an http get request, with 5 seconds sleep between each request.

const taskAsyncLoop = require("task-async-loop");
taskAsyncLoop({
    delay: 5000,
    executer: (data, next, stop, setDelay) => {
        const req = require("https").request(
            {
                hostname: "jsonplaceholder.typicode.com",
                port: 443,
                path: "/todos/1",
                method: "GET"
            },
            (res) => {
                let data = "";

                res.on("data", (chunk) => {
                    data += chunk;
                });

                res.on("end", (d) => {
                    console.log(data);
                    // The whole response has been received. go to next iteration
                    next();
                });
            }
        );

        req.on("error", (error) => {
            console.error(error);
            // got error, stop iterations
            stop();
        });

        req.end();
    }
});

License

MIT License