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

enque

v1.2.5

Published

Run asynchonous functions in succession while potentially operating on the same data.

Downloads

6

Readme

enQue.js

Chain asynchronous functions in succession, consuming the same data stream.

const Que = new require('enQue');
Que([fn1, fn2, fn3, fn4, fn5]).run(data).then(data=>YOUR_CALLBACK(data));
// Where each fn follows the format fn(data, next) { /*example: */ data.size++; next() } 
// data must be an OBJECT! ie: myQue.run({text:"Hi"}) then in your callback its data.text

For full documentation see the enQue full docs.

Features

1.) Skip ahead in the que next(4) would skip to position 4.

2.) Go backwards in the que next(-4) would go back 4.

3.) Inject a Function at a particular que index next({inject:4,function:Function}). (runs parallel to que not sync'd)

4.) Quit after a specified amount of que spots next({quit:4}) quits after 4 more iterations.

5.) Allows removing functions from the que by index, variable name, or raw text.

6.) A fill method for convenience.

The above code snippet illustrates how simple it would be to execute 5 asynchronous functions in succession that all operate on the same data. When you add a function to the que accept the second a parameter (data is first) and make sure to call it for example FUNCTION_NAME(data, next) { /* example: */ data.size + 1; /* MANDATORY */ next() }. You can also use next(0) to quit early. The entire point of this package is that each spot in the que wont run untill the last spot has said ok im done via calling next(), or whatever you chose to name it.

Since a promise is returned it is always best to attach a .then() and .catch() so the above code would become.

myQue.run(data)
  .then(sucessCallback); // Passed 1 argument, the data OBJECT.
  .catch(errorCallback); // Passed 1 argument, the error.

Instalation

npm install enque

Dependencies

None.

Usage examples

// USAGE EXAMPLE
const Que = require('enQue');
const que = new Que();

// Used to only go backwards once, otherwise you end up in an infinite cycle.
// IF YOU GO FORWARD IN THE QUE YOU CANNOT GO BACKWARDS TO A PLACE NOT ON THE NEW QUE
// It will throw a error if you attempt to go forward then backwards.
var once = true;

que.add((data, next, done, index) => {
  // index is the position of your function in the que, 0 right now.
  //return done(); // You can return early if you'd like
  setTimeout(()=>{
    data.msg += ' ONE';
    // You can inject a function at a specified relative position (it isnt added to the que, it runs parallel so careful here).
    //next({inject:7, function: function(data) {data.msg += " ONE AND A HALF";}}); // This would run that function after 7 more que'd fn's are done.
    next()
  }, 9000)
});
que.add((data, next) => {
  setTimeout(()=>{
    //throw "errors work too" // You can throw an error and reject the promise
    data.msg += ' TWO';
    next();
  }, 4000)
});
que.add((data, next) => {
  data.msg += ' THREE';
  next()
});

function myFn1(data, next) {
  data.msg += ' FOUR';
  // You can go backwards in the que.
  if(once) { once = false; next(-2); }
  // You can go forwards in the que.
  else next(1);
}

function myFn2(data, next) {
  data.msg += ' FIVE';
  next();
}

// You can add multiple functions at a time.
que.add([myFn1, myFn2]) 

que.run({msg: 'ZERO'})
  .then(res => console.log(res.msg))
  .catch(err => console.log('Woopsie! ' + err))

Executing the above code as is gives:

ONE TWO THREE FOUR TWO THREE FOUR FIVE

More examples

NOTE You can't actually call que.run() then que.clear() because the que may still be processing. You need to call. que.run().then(()=>que.clear()) or to extract data from the processed que que.run().then(data=>YOUR_CALLBACK(data)). Each function in your que is handed data as a first parameter whether or not you originally passed one in. default {}

// For the purpose of these examples, assume each function is asynchronous and you don't know when it will finish execution.
// When operating on the data it is important to remember that it must not be a primitive. If you must operate on just a primitive
// set it to an attribute on an object. for example if you need to operate on a `Number` you can do `que.run({data.number=17})`.

Que = require('enQue');
que = new Que();

function fn1(data, next) {
 console.log(1);
 next();
}
function fn2(data, next) {
 console.log(2);
 next();
}

que.add(fn1);
que.run(); // 1
que.clear();

que.add([fn1, fn1, fn1]);
que.run(); // 1 1 1
que.clear();

que.fill(fn1, 7);
que.run();
que.clear(); // 1 1 1 1 1 1 1 

que.add([fn1, fn1, fn1]);
que.remove(fn1);
que.run(); // ""

que.add([fn1, fn2, fn2, fn2]);
que.remove([fn1, fn2], 3); // for best preformance only pass in numbers i.e. `remove(0); remove(1); remove(2)`
que.run(); // 2
que.clear();

que.add([(d,n)=>n(5), fn1, fn1, fn1, fn1, fn1, fn1]);
que.run(); // 1
que.clear();

que.add([(d,n)=>n({quit:3}), fn1, fn1, fn1, fn2, fn2, fn2]);
que.run(); // 1 1 1
que.clear();

que.add((d,n,i)=>{console.log("hi"); n()});
que.remove('(d,n,i)=>{console.log("hi"); n()}');
que.run(); // ""

fn5 = (data, next, index, done) => {
  console.log(index);
  index === 2 ? next(0) : next();
  // instead of next(0) you can use done()
}

que.add([fn5, fn5, fn5, fn5, fn5]);
que.run(); // 0 1 2
que.clear();

fn3 = (data, next) => {
 data.data = "SEVEN";
 next();
}

que.add([(d,n)=>n({inject:5, function: function(d){d.data="7"}}), fn3, fn3, fn3, fn3, fn3]);
que.run().then(res=>console.log(res)); // d.data === 7
// To initialise the data use `run(data)` where data is an Object.
que.clear();

function fn6(data, next, index) {
  throw new Error("Woopsie!");
  next();
}

que.add([fn6, fn6, fn6, fn6, fn6]);
que.run().catch(e=>console.log(e)); // prints the thrown error.

Executing the above code as is gives:

1
1
1
1
1
1
1
1
1
1
1
2
1
1
1
1
0
1
2
{ data: '7' }
Error: Woopsie!
    at fn6 (...)
    at options (...)
    at enQue.executeQue (...)
    at ...
    ...