Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
The 'after' npm package is a small utility that helps manage asynchronous operations by executing a callback after a specified number of operations have completed. It is particularly useful for scenarios where you need to wait for multiple asynchronous tasks to finish before proceeding.
Execute callback after multiple asynchronous operations
This feature allows you to specify a callback function that will be executed after a certain number of asynchronous operations have completed. In this example, the callback will be executed after three tasks have finished.
const after = require('after');
const done = after(3, () => {
console.log('All tasks completed');
});
setTimeout(() => {
console.log('Task 1 done');
done();
}, 1000);
setTimeout(() => {
console.log('Task 2 done');
done();
}, 2000);
setTimeout(() => {
console.log('Task 3 done');
done();
}, 3000);
The 'async' package provides a wide range of utilities for working with asynchronous JavaScript, including functions for parallel and series execution, queue management, and more. It is more feature-rich compared to 'after' and can handle more complex asynchronous workflows.
The 'promise' package is a lightweight implementation of Promises/A+ that allows you to work with asynchronous operations in a more modern and flexible way compared to callbacks. It provides methods like 'all' and 'race' to manage multiple promises, making it a more versatile option than 'after'.
The 'bluebird' package is a fully-featured Promise library that offers advanced features like cancellation, iteration methods, and more. It is more powerful and flexible than 'after', making it suitable for complex asynchronous workflows.
All the flow control you'll ever need
var after = require("after"),
next = after(3, logItWorks);
next();
next();
next(); // it works
function logItWorks() {
console.log("it works!");
}
Minimal flow control. A lot of the libraries out there are over kill. I want a small tool that gives me fundamental concrete building blocks
after
takes a count and a callback and returns a function next
. The callback get's invoked when the next
function is invoked count number of times. The callback aggregates the data given to next
as un-ordered parameters.
var next = after(3, printData);
next("foo", "bar", { ... })
next({ ... });
next(42);
function printData() {
for (var i = 0, len = arguments.length; i < len; i++) {
console.log(arguments[i]);
}
// in some order
// 42
// { ... }
// [ "foo", "bar", { ... }]
}
Note that the internal counter is exposed as next.count
so you can manually increment or decrement it in a dynamic fashion. This is useful for recursively algorithms that want to increment the counter.
Unpack data from after using a convention
var next = after(2, function () {
var data = after.unpack(arguments);
/* data = { foo: "bar", baz: "boz"}; */
});
next("foo", "bar");
next("baz", "boz");
The following methods are asynchronous parallel versions of the Array.prototype
methods.
They all take parameters (set, iterator, optionalContext, finishedCallback)
(callback)
or (value, callback)
or (value, index, callback)
or (value, index, obj, callback)
. The last argument is always the callback. The callback should be invoked when your done iterating over that item. You may invoke the callback with (err, result)
this
inside the iterator(err, result)
. The err
parameter
is whatever passed an error first or null
. The result parameter is specific
to each set utility functionNote that reduce
has an optionalInitialValue
instead of an optionalContext
.
Also reduce's signature is (memo, value, index, obj, callback)
or any of the shorter forms like (memo, value, callback)
.
Apart from reduce and reduceRight all of these set iterators run their iterators in parallel over the set
For .forEach
the result
parameter of the finishedCallback is always undefined.
var set = {
google: googleUser,
github: githubUser,
facebook: facebookUser
};
after.forEach(set, synchronizeOAuth, finished)
function synchronizeOAuth(userObject, oAuthName, callback) {
getOAuth(oAuthName).sychronize(userObject, callback);
}
function finished(err) {
if (err) throw err;
}
For .map
the result
parameter of the finishedCalllback is the object your mapping too.
map will return a result that either inherits from your objects prototype or is an array depending on whether the call value is an object or an array
var set = {
google: googleUser,
github: githubUser,
facebook: facebookUser
};
after.map(set, getOAuthUser, finished);
function getOauthUser(userObject, oAuthName, callback) {
getOAuth(oAuthName).getUser(userObject, callback);
}
function finished (err, oAuthUserObjects) {
if (err) throw err;
for (var service in oAuthUserObjects) {
...
}
}
For .reduce
the result
parameter is the reduced value.
var set = {
google: googleUser,
github: githubUser,
facebook: facebookUser
};
after.reduce(set, aggregateFriends, 0, finished);
function aggregateFriends(memo, userObject, oAuthName, callback) {
getOAuth(oAuthName)
.getNumberOfFriends(userObject, function (err, friends) {
callback(err, friends + memo);
});
}
function finished (err, numberOfFriends) {
if (err) throw err;
...
}
.reduceRight
is the same as reduce
excepts runs over the object in reverse.
For .filter
the result
is the filtered object/array.
var set = {
google: googleUser,
github: githubUser,
facebook: facebookUser
};
after.filter(set, isRegistered, finished);
function isRegistered(memo, userObject, oAuthName, callback) {
getOAuth(oAuthName).userExists(userObject, callback);
}
function finished (err, usersThatExist) {
if (err) throw err;
...
}
Every passes true
to the finished callback if every callback in the iteration passed true
.
var set = {
google: googleUser,
github: githubUser,
facebook: facebookUser
};
after.every(set, isRegistered, finished);
function isRegistered(memo, userObject, oAuthName, callback) {
getOAuth(oAuthName).userExists(userObject, callback);
}
function finished (err, registeredOnAllServices) {
if (err) throw err;
...
}
Some passes false
to the finished callback if every callback in the iteration passed false
.
var set = {
google: googleUser,
github: githubUser,
facebook: facebookUser
};
after.every(set, isRegistered, finished);
function isRegistered(memo, userObject, oAuthName, callback) {
getOAuth(oAuthName).userExists(userObject, callback);
}
function finished (err, registeredOnAnyServices) {
if (err) throw err;
...
}
npm install after
make test
FAQs
after - tiny flow control
The npm package after receives a total of 1,744,641 weekly downloads. As such, after popularity was classified as popular.
We found that after demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.