micro-tasks

microTasks

Library to execute JSON task with declarative programming. It converts a JSON collection into a list of actions (asynchronous or not), executes them and returns the result. It also efficiently manages possible errors.

How it does work?

The next example JSON declares 5 actions that manage an ajax request to get the data of a user’s shopping cart. This task returns the products of the cart and the total price, or a 500 http error if there is a problem.

microTasks.taskRun([
  {
    // get from mysql db the user id
    // and set it in 'payload.userId'
    method: 'mysql.query',
    params: {
      query: 'SELECT id FROM users WHERE email=""',
      handler: 'field'
    },
    resultPath: 'userId'
  },
  {
    // get from mysql db the units and prices of the product of the cart of this user
    // and set it in 'payload.cartProducts' as array
    method: 'mysql.query',
    params: {
      query: 'SELECT units, price FROM cart WHERE userId=',
      handler: 'rows'
    },
    resultPath: 'cartProducts'
  },
  {
    // map 'payload.cartProducts' multiplying units by price and set the result in totalByProduct property
    // and set it in 'payload.cartProducts'
    method: 'collection.mapByIterator',
    params: ['{payload.cartProducts}', 'math.multiply', 'totalByProduct', 'units', 'price'],
    resultPath: 'cartProducts'
  },
  {
    // reduce 'payload.cartProducts' adding totalByProduct
    // and set it in 'cartTotalPrice'
    method: 'collection.reduce',
    params: ['math.add', 'totalByProduct'],
    resultPath: 'cartTotalPrice'
  },
  {
    // response the ajax request with cartProducts, cartTotalPrice and status code
    method: 'request.response',
    params: {
      status: 200,
      cartTotalPrice: '{payload.cartTotalPrice}',
      cartProducts: '{payload.cartProducts}'
    }
  },
  {
    // response the ajax request with error
    catch: true,
    method: 'request.response',
    params: {
      status: 500,
      error: 'Internal error'
    }
  }
], {
  email: 'info@example.com'
})

Each action becomes a promise. Unknown errors can be managed with catch property.

The previous example would become something like:

const payload = {}
new Promise((resolve) => resolve())
  .then(() => {
    return mysqlConnect()
  })
  .then(() => {
    return mysqlQuery('SELECT id FROM users WHERE email="info@example.com"')
  })
  .then((userId) => {
    payload.userId = userId
  })
  .then(() => {
    return mysqlQuery('SELECT units, price FROM cart WHERE userId=123')
  })
  .then((cartProducts) => {
    payload.cartProducts = cartProducts
  })
  .then(() => {
    payload.cartProducts = payload.cartProducts.map((cartProduct) => {
      cartProduct.totalByProduct = cartProduct.units * cartProduct.price
      return cartProduct
    })
  })
  .then(() => {
    payload.cartTotalPrice = payload.cartProducts.reduce((total, cartProduct) => {
      total += cartProduct.totalByProduct
    }, 0)
  })
  .then(() => {
    request.send({ cartTotalPrice: payload.cartTotalPrice, cartProducts: payload.cartProducts }).status(200)
  })
  .catch(() => {  
    request.send({ error: 'Internal error' }).status(500)
  })

Basic concepts

Debug

To facilitate the debugging of tasks, each action logs:

This action logs next data (example):

microTasks.taskRun([{
  if: {
    method: 'conditionalAction',
    params: '{payload.myCondition}',
    equalTo: true
  },
  method: 'print',
  params: 'This action is executed because conditionalAction is ok'
}], {
  myCondition: true
})

/*
{  
  if: {  
    method: "conditionalAction",
    params: "{payload.myCondition}",
    parsedParams: [true],
    equalTo: true,
    resultValue: true
  },
  method: "print",
  params: "This action is executed because conditionalAction is ok",
  parsedParams: ["This action is executed because conditionalAction is ok"],
  status: "solved",
  time: {  
    start: 1511375841559,
    end: 1511375841576,
    duration: 17
  }
}
*/

Documentation

We recommend you read the basic concepts, see a couple of examples and then read the documentation:

Libraries

We have created the following libraries with the methods and actions most used in projects. To use the libraries you just have to import them in your application.

Examples

Setup and NPM scripts

npm install
npm start # run examples/hello-world.js
npm run devtool # run examples/hello-world.js with devtool
npm run lint
npm run docs