/promises-runner

Run promises from an array of objects waiting for some promises to be resolved before continuing running others

Primary LanguageJavaScript

promises-runner

Build Status

NPM

Run promises from an array of objects waiting for some promises to be resolved before continuing running others

Install

npm install --save promises-runner

Api

PromisesRunner({
    objectsArrayWithPromises: [Object],                 // default []
    inputData: Object,                                  // default {}
    outputDataKey: string|false,                        // default false
    mergePromiseOutputToNextPromiseInput: true|false,   // default false
    mergeSameKeyByConvertingToArray: true|false,        // default false
    logger: Function|false         // default false
    })

objectsArrayWithPromises single object should be {promise: (inputData) => Promise, wait: true|false, outputKey: string}

logger function logger: (action: String, objectFromArrayWithPromises: Object, inputOutputOrError: Mixed) action = START|ERROR|DONE objectFromArrayWithPromises = one object from objectsArrayWithPromises with (promiseName) inputOutputOrError = would be input of promise if action = START, output of promise if action = DONE and error if action = ERROR

Check example logger function at end of README

Usage example

var PromisesRunner = require('promises-runner')

function expensiveOperation(value) {
  return Promise.resolve(value)
}
const objectsArrayWithPromises = [
    {promise: expensiveOperation},              // <--┐
    {promise: expensiveOperation},              // <----- these will run in parallel
    {promise: expensiveOperation},              // <--┘
    {promise: expensiveOperation, wait: true},  // this will wait before all previous are resolved
    {promise: expensiveOperation},              // these 2 -- after the previous one is resolved
    {promise: expensiveOperation},              // these 2 -- and are ran in parallel
    {promise: expensiveOperation, wait: true},  // this will wait before all previous are resolved
    {promise: expensiveOperation},              // these 2 -- after the previous one is resolved
    {promise: expensiveOperation},              // these 2 -- and are ran in parallel
]
var pr = new PromisesRunner({objectsArrayWithPromises});

pr.start();

// pause/resume PromisesRunner
const resume = pr.pause();
resume();

// stop promises runner,
// this will send currentOutput and
// promise.then will be called after completion of promises already running (parallel ones)
const currentOutput = pr.stop();

Example of objects being merged as per outputKey and mergePromiseOutputToNextPromiseInput

const sleepFor = (seconds, value, valueAs, d) => new Promise(resolve => (
    setTimeout(() => resolve(value ? {[valueAs]: value} : {}), seconds)
));
const allPromises = [
            {promise: (d) => sleepFor(1, 'action1', 'a1', d)},
            {promise: (d) => sleepFor(3, 'action2', 'a2', d)},
            {promise: (d) => sleepFor(1, 'action3w', 'a3', d), wait: true},
            {promise: (d) => sleepFor(8, 'action4', 'a4', d)},
            {promise: (d) => sleepFor(1, 'action5', 'a5', d)},
            {promise: (d) => sleepFor(2, 'action6w', 'a6', d), wait: true},
            {promise: (d) => sleepFor(2, 'action7', 'a7', d)},
            {promise: (d) => sleepFor(5, 'action8w', 'a8', d), wait: true},
            {promise: (d) => sleepFor(2, 'action9', 'a9', d)},
            {promise: (d) => sleepFor(1, 'action10', 'a10', d), outputKey: 'abc'},
        ];

        new PromisesRunner({
            objectsArrayWithPromises: allPromises, 
            inputData: {someInputData: -1},
            outputDataKey: 'outputKey',                 // default false
            mergePromiseOutputToNextPromiseInput: true  // default false
        })
            .start()
            .then(console.log)
            
/* 
for outputDataKey = 'outputKey', mergePromiseOutputToNextPromiseInput = true
input for all promises: {someInputData: -1, outputKey: {a1: 'action1', a2: 'action2' ....}}
output: 
{
    outputKey: { 
        a1: 'action1',
        a2: 'action2',
        a3: 'action3w',
        a4: 'action4',
        a5: 'action5',
        a6: 'action6w',
        a7: 'action7',
        a8: 'action8w',
        a9: 'action9',
        abc: {
            a10: 'action10'
        }
    }
}
*/
/* 
for outputDataKey = false, mergePromiseOutputToNextPromiseInput = true
input for all promises: {someInputData: -1, a1: 'action1', a2: 'action2' ....}
output: 
{
    a1: 'action1',
    a2: 'action2',
    a3: 'action3w',
    a4: 'action4',
    a5: 'action5',
    a6: 'action6w',
    a7: 'action7',
    a8: 'action8w',
    a9: 'action9',
    abc: {
        a10: 'action10'
    }
}
*/
/* 
for default outputDataKey = false, mergePromiseOutputToNextPromiseInput = false
input for all promises: {someInputData: -1}
output: 
{
    a1: 'action1',
    a2: 'action2',
    a3: 'action3w',
    a4: 'action4',
    a5: 'action5',
    a6: 'action6w',
    a7: 'action7',
    a8: 'action8w',
    a9: 'action9',
    abc: {
        a10: 'action10'
    }
}
*/

Example logger taskLogger.js

const chalk = require('chalk');
const lowerCase = require('lodash/lowerCase');
const pad = require('lodash/pad');
module.exports = (action, relatedPromiseRunnerObject, relatedData) => {
    let consoleColor = chalk;
    switch (action) {
        case 'START':
            consoleColor = chalk.bgKeyword('orange');
            break;
        case 'DONE':
            consoleColor = chalk.bgKeyword('green');
            break;
        case 'ERROR':
            consoleColor = chalk.bgKeyword('red');
            break;
    }
    console.log(consoleColor(`[${pad(action, 9)}]`), '==>', lowerCase(relatedPromiseRunnerObject.promiseName));
};