Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
move-on
is a very light module that creates a chain of synchronous or asynchronous functions and sets its own inner userContext object for this
keyword for all chained functions.
move-on
module function executes the functions sequentially in the chain.
The done
function is called when the last function from the chain is resolved.
move-on
all
static method executes all the functions simultaneously.
The done
function is called when all functions from the chain are resolved.
Any bugs found? Give me to know on dev.rafalko@gmail.com or on GitHub
npm install move-on
const moveOn = require('move-on');
const functionList = [funA, funB];
const userContext = {};
moveOn(functionList, userContext, onDone, onError);
function funA(resolve,reject){
resolve();
}
function funB(resolve,reject){
resolve();
}
function onDone(userContext,reject){
console.log('all functions succeeded!');
//continuation code here
}
function onError(userContext,msg){
console.error(msg);
}
moveOn(list, userContext, done, catch)
moveOn.all(list, userContext, done, catch)
list
[Array]arrow functions
. They cannot be binded, so the userContext
will not be set for them.userContext
[Object|null]userContext
Object.userContext
Object by this
keyword.userContext
properties can be set and get in any queued function, thereby shared between each function of the queue block.{}
to create the new userContect
for the chain.this
reference), set userContext
to null
done(userContext,reject)
[Function]done
is automatically attached at the end of the chain and called as the last one (if all previous functions have been resolved). [sample]done
:
this
; It is useful if you define done
function as an arrow function
(arrow functions
are not intended to be binded by default, so the access to the userContext this
object can be gained only via the argument).reject
function; You can still reject the chain in the done
function by calling reject()
.catch(userContext)
[Function]catch
is automatically attached at the end of the chain as catch()
function and executed in case of the rejection of any queued function (when the reject()
is called).catch
:
this
; It is useful if you define catch
function as an arrow function
(arrow functions
are not intended to be binded by default, so the access to the userContext this
object can be gained only via the argument).resolve
and [Function] reject
arguments are passed through each chained [Function] item.resolve
is called, the further chained [Function] item is called.reject
is called, the catch
callback function is called. [see below]resolve
and reject
can be called with any number of arguments. They will be passed to the further function in the chain, when resolved, or to the catch
function, when rejected. [see below]function fetchData(resolve,reject){
if(foo) {
resolve(foo);
} else {
reject('foo is not defined.');
}
}
resolve
and reject
do not end function execution. In order to end function execution, use return resolve()
or return reject()
. [sample]resolve
and reject
can be called many times in the same function:
resolve
callback function twice, it runs the further part of the chain twice. You can, for example, call the resolve
function once, then redefine the properties in the userContext this
object, then call resolve
again.resolve
in the for
loop. [sample]reject
twice for example to pass two different error messages to the catch
function. [sample]const moveOn = require('move-on');
//set the list of functions in order
const functionList = [setInitialData,getName,getAge];
//set the userContext accessible via this keyword
const userContext = {};
moveOn(functionList, userContext, onDone, onCatch);
function onDone(userContext,reject){
console.log(`The new employee of ${this.company} company, based in ${this.city}, is ${this.age}yo ${this.name}.`);
//=> The new employee of PierogSoft company, based in Warsaw, is 26yo John Doe.
}
function onCatch(userContext,msg){
console.log('Something went wrong: ',msg);
}
function setInitialData(resolve,reject){
//this is a sample of synchronous function in the chain
//this data will be accessible via this keyword in all chained functions
this.company = 'PierogSoft';
this.city = 'Warsaw';
resolve();
}
function getName(resolve,reject){
//this is a sample of asynchronous function in the chain
//it runs resolve() when it's ready
setTimeout(()=>{
//mind that arrow function takes userContext this from the parent function
this.name = 'John Doe';
resolve();
},1000);
}
function getAge(resolve,reject){
//this is another sample of asynchronous function in the chain
//it runs resolve() when it's ready
setTimeout(()=>{
//mind that arrow function takes userContext this from the parent function
this.age = 26;
resolve();
},600);
}
userContext
object is defined with some initial properties.resolve
and reject
functions.const moveOn = require('move-on');
//set userContext object with some initial properties
const userContext = {
name:'John Doe',
age:25
};
moveOn([check], userContext, onDone, onCatch);
function check(resolve,reject){
//check if initial properties are accessible
console.log(this.name); //John Doe
console.log(this.age); //25
if(this.name&&this.age){
//pass the argument to the further function
resolve('person');
} else {
//pass the argument to the catch function
reject('The person was not defined.');
}
}
function onDone(userContext,reject,isPerson){
//get the 'isPerson' argument pass in the previous function
if(isPerson==='person') console.log(`New person: ${this.name} (${this.age}yo).`);
}
function onCatch(userContext,msg){
console.log('Something went wrong: ',msg);
}
catch
function immediately.const moveOn = require('./index.js');
moveOn([a,b,c], {}, onDone, onCatch);
function a(resolve,reject){
resolve();
}
function b(resolve,reject){
reject('oops!');
}
function c(resolve,reject){
//it's been never called!
resolve();
}
function onDone(userContext,reject){
//it's been never called!
}
function onCatch(userContext,msg){
console.log(msg); //oops!
}
return resolve()
ends the function.resolve()
works in the further functions.const moveOn = require('move-on');
moveOn([a,b,c], {}, onDone, onCatch);
function a(resolve){
resolve();
console.log('this is still logged!');
//lets define some properties after resolve() call
this.name = 'John Doe';
this.age = 25;
}
function b(resolve){
//properties are inaccessible because they were defined after this function was executed
console.log(this.name); //undefined
console.log(this.age); //undefined
return resolve();
console.log('this is nog logged');
}
function c(resolve){
setTimeout(()=>{
//properties are accessible because c function works asynchronously
console.log(this.name); //John Doe
console.log(this.age); //25
resolve();
},500);
}
function onDone(userContext,reject){
//properties are accessible because onDone function is fired after async c function is resolved
console.log(this.name); //John Doe
console.log(this.age); //25
}
function onCatch(userContext){
//it's been never called
}
this
as the userContext
object.const moveOn = require('move-on');
moveOn([a,b,c], {}, onDone, onCatch);
/* Order of executions:
* a
* x
* y
* z
* b
* c
*/
function a(resolve){
resolve();
}
function b(resolve){
//lets define some properties
this.name = 'John Doe';
this.age = 25;
//set this as the userContext of the inner queue
moveOn([x,y,z], this, function(){
resolve(); //resolve b after x, y and z are succeeded!
}, onCatch); //one onCatch function for all rejected functions
}
function c(resolve){
resolve();
}
function x(resolve){
//check if the parent userContext is accessible
console.log(this.name); //John Doe
resolve();
}
function y(resolve){
resolve();
}
function z(resolve){
resolve();
}
function onDone(userContext,reject){
console.log('Success!');
}
function onCatch(userContext){
//it's been never called
}
resolve()
behave.const moveOn = require('move-on');
moveOn([a,b,c], {}, onDone, onCatch);
/* Order of executions:
a before
x before
y before
z before
b before
c before
DONE!
c after
b after
z after
y after
x after
a after
*/
function a(resolve){
console.log('a before');
resolve();
console.log('a after');
}
function b(resolve){
moveOn([x,y,z], this, function(){
console.log('b before');
resolve();
console.log('b after');
}, onCatch);
}
function c(resolve){
console.log('c before');
resolve();
console.log('c after');
}
function x(resolve){
console.log('x before');
resolve();
console.log('x after');
}
function y(resolve){
console.log('y before');
resolve();
console.log('y after');
}
function z(resolve){
console.log('z before');
resolve();
console.log('z after');
}
function onDone(userContext,reject){
console.log('DONE!');
}
function onCatch(userContext){
//it's been never called
}
const moveOn = require('./index.js');
const productsData = {
id: ['ab12','xy34'],
products:[]
};
moveOn([init,findPrice,isAvailable], productsData, onDone, onCatch);
function init(resolve){
this.iter = 0; //set iter to find out when all async functions are done
for(let i in this.id){
//run findPrice() and isAvailable() back-to-back for each ID
resolve(this.id[i]);
}
}
function findPrice(resolve,reject,getID){
setTimeout(()=>{
//assume that we asynchronously fetch the price due to the ID of the product
var price = Math.round(Math.random()*100)+'$';
resolve(getID,price);
},500);
}
function isAvailable(resolve,reject,getID,getPrice){
setTimeout(()=>{
//assume that we check if the product of specified ID is available
var available = Math.random()>.5;
//save the data about the product
this.products.push({id:getID,price:getPrice,available:available});
this.iter++;
//if this is the last async function, resolve() and finish the chain
if(this.iter===this.id.length) resolve();
},500);
}
function onDone(userContext,reject){
console.log('Success!');
console.log(this.products);
//{ id: 'ab12', price: '71$', available: true },
//{ id: 'xy34', price: '31$', available: false }
}
function onCatch(userContext){
//it's been never called
}
reject()
execution can be used for a validation.const moveOn = require('move-on');
const validFunctions = [
isString,
hasAtSign,
hasMultipleAtSigns,
hasSpecialChars,
hasSpaces,
hasDoubleDots,
isAvailable
];
const address = {
email: 'John..doe@gm@ail.com'
};
moveOn(validFunctions, address, onDone, onCatch);
/* console =>
* Invalid: The value can contain only one @ sign.
* Invalid: The value cannot contain capital letters.
* Invalid: The value cannot contain double dots.
* Invalid: The John..doe@gm@ail.com address is unavailable.
*/
function isString(resolve,reject){
if(typeof this.email !=='string') return reject('The value must be a String.');
resolve();
}
function hasAtSign(resolve,reject){
if(!(/@/).test(this.email)) reject('The value must contain @ sign.');
resolve();
}
function hasMultipleAtSigns(resolve,reject){
if((/@.*@/).test(this.email)) reject('The value can contain only one @ sign.');
resolve();
}
function hasSpecialChars(resolve,reject){
if(!(/^[a-z.\-@_]+$/).test(this.email)) reject('The value cannot contain capital letters.');
resolve();
}
function hasCapitals(resolve,reject){
if((/[A-Z]/).test(this.email)) reject('The value cannot contain special characters.');
resolve();
}
function hasSpaces(resolve,reject){
if((/\s/).test(this.email)) reject('The value cannot contain spaces.');
resolve();
}
function hasDoubleDots(resolve,reject){
if((/\.{2,}/).test(this.email)) reject('The value cannot contain double dots.');
resolve();
}
function isAvailable(resolve,reject){
//this.atLeastOneErr is set in the onCatch() function
//if the address is invalid, it makes no sense to check if is available
if(this.atLeastOneErr) return;
setTimeout(()=>{
var available = Math.random()>.5;
if(available) resolve(`Success! The ${this.email} address is available!`);
if(!available) reject(`The ${this.email} address is unavailable.`);
},234);
}
function onDone(userContext,reject,msg){
console.log(msg);
}
function onCatch(userContext,msg){
this.atLeastOneErr = true;
console.log('Invalid: ' + msg);
}
FAQs
Creates a queue of sync or async functions with resolve and reject callback.
The npm package move-on receives a total of 2,855 weekly downloads. As such, move-on popularity was classified as popular.
We found that move-on demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.