1.0.6 • Published 5 years ago

batching v1.0.6

Weekly downloads
26
License
ISC
Repository
github
Last release
5 years ago

Batching

Map multiple call async functions that have the same context with the earliest result returned.

Usage

Assume you have a slow API

async function slowDoubleAPI(a) {
  console.log(`slowDoubleAPI(${a})`);
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (typeof a !== 'number') {
        reject(new Error(`a param expect a number, but received ${a}`));
      }
      resolve(a * 2);

    }, _.random(500, 700));
  });
}

and make a batch call

async function testWithoutBatch() {
  try {
    let results = await Promise.all([
      slowDoubleAPI(1),
      slowDoubleAPI(2),
      slowDoubleAPI(1),
      slowDoubleAPI(1),
      slowDoubleAPI(2),
      slowDoubleAPI(3),
      slowDoubleAPI(1),
      slowDoubleAPI(2),
      slowDoubleAPI(1),
      slowDoubleAPI(1),
      slowDoubleAPI(2),
      slowDoubleAPI(1),
      slowDoubleAPI(1),
      slowDoubleAPI(2),
      slowDoubleAPI(3),
      slowDoubleAPI(1),
      slowDoubleAPI(2),
      slowDoubleAPI(1),
    ]);
    console.log('RESULT : ', results);
  }
  catch (err) {
    console.log(`ERROR ${err.message}`);
  }
};

testWithoutBatch();

You realize that a lot of calls have the same context, and don't want to repeat it.

slowDoubleAPI(1)
slowDoubleAPI(2)
slowDoubleAPI(1)
slowDoubleAPI(1)
slowDoubleAPI(2)
slowDoubleAPI(3)
slowDoubleAPI(1)
slowDoubleAPI(2)
slowDoubleAPI(1)
slowDoubleAPI(1)
slowDoubleAPI(2)
slowDoubleAPI(1)
slowDoubleAPI(1)
slowDoubleAPI(2)
slowDoubleAPI(3)
slowDoubleAPI(1)
slowDoubleAPI(2)
slowDoubleAPI(1)
RESULT :  [ 2, 4, 2, 2, 4, 6, 2, 4, 2, 2, 4, 2, 2, 4, 6, 2, 4, 2 ]

Let batch them ...

const batch = require('batching');

async function testWithBatch() {
  try {
    let results = await Promise.all([
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [2]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [2]),
      batch(slowDoubleAPI, [3]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [2]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [2]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [2]),
      batch(slowDoubleAPI, [3]),
      batch(slowDoubleAPI, [1]),
      batch(slowDoubleAPI, [2]),
      batch(slowDoubleAPI, [1]),
    ]);
    console.log('RESULT : ', results);
  }
  catch (err) {
    console.log(`ERROR ${err.message}`);
  }
};

testWithBatch();

The first call slowDoubleAPI(1) will be executed, but later call slowDoubleAPI(1) before first call finish won't, just push to queue, and assign them to the first call result when it finishes.

slowDoubleAPI(1)
slowDoubleAPI(2)
slowDoubleAPI(3)
RESULT :  [ 2, 4, 2, 2, 4, 6, 2, 4, 2, 2, 4, 2, 2, 4, 6, 2, 4, 2 ]

Let turn on log to view detail :

batch.setLog(true);

Will print :

[batch] slowDoubleAPI() start, with :
 * ARGS        :  [1]
 * THIS        :  undefined

slowDoubleAPI(1)
[batch] slowDoubleAPI() start, with :
 * ARGS        :  [2]
 * THIS        :  undefined

slowDoubleAPI(2)
[batch] slowDoubleAPI() start, with :
 * ARGS        :  [3]
 * THIS        :  undefined

slowDoubleAPI(3)
[batch] slowDoubleAPI() finish successful, with :
 * TIME        :  601ms
 * ARGS        :  [3]
 * THIS        :  undefined
 * Callbacks   :  2
 * RESULT      :  6

[batch] slowDoubleAPI() finish successful, with :
 * TIME        :  644ms
 * ARGS        :  [1]
 * THIS        :  undefined
 * Callbacks   :  10
 * RESULT      :  2

[batch] slowDoubleAPI() finish successful, with :
 * TIME        :  676ms
 * ARGS        :  [2]
 * THIS        :  undefined
 * Callbacks   :  6
 * RESULT      :  4

API

Batch(options) ⇒ function

Create new batch

Kind: global function
Returns: function - batch

ParamTypeDefaultDescription
optionsobject
options.logStartboolean | functionfalseinterface : (asyncFunc : function, context : object) => void
options.logFinishboolean | functionfalseinterface : (asyncFunc : function, context : object, err : object, res : any) => void
options.isArgsEqualfunction_.isEqualarguments comparator
options.isThisEqualfunction_.isEqualthis pointer comparator

Example

const { Batch } = require('batching');

const custom_batch = Batch({
  isArgsEqual : (a, b) => a[0] === b[0],
  isThisEqual : (a, b) => a === b,
  logFinish   : true
});


Batch~wrap(asyncFunc, thisArg) ⇒ function

Wrap a async function to support batching

Kind: inner method of Batch
Returns: function - batchedAsyncFunction : (...args) => Promise

ParamType
asyncFuncfunction
thisArgany

Example

// Instead of : 
const batch = require('batching');

let user1 = await batch(findOne, { id : 10000 }, UserModel);
let user2 = await batch(findOne, { id : 10001 }, UserModel);
let user3 = await batch(findOne, { id : 10000 }, UserModel);

// Use can wrap findOne() :

const batchedFindOne = batch.wrap(findOne, UserModel);

// And call it :

let user1 = await batchedFindOne({ id : 1000 });
let user2 = await batchedFindOne({ id : 1001 });
let user3 = await batchedFindOne({ id : 1000 });


Batch~batch(asyncFunc, args, thisArg) ⇒ Promise

Map multiple call async functions that have the same context with the earliest result returned.

Kind: inner method of Batch
Returns: Promise - that return by first finished invoking

ParamType
asyncFuncfunction
argsarray
thisArgobject

Example

const batch = require('batching');

let store = await batch(findOneStore, [{ id : 10010 }]);

// with thisArg
let store = await batch(findOne, [{ id : 10010 }], StoreModel);


Batch~setLog(options)

Set log options

Kind: inner method of Batch

ParamTypeDescription
optionsboolean | objectturn log on or off, or customer log function

Example

// set all log
batch.setLog(true);

// set specific log
batch.setLog({
  logStart : false,
  logEnd   : true,
});

// custom log function
batch.setLog({
  logStart : (asyncFunc, context) => {},
  logEnd   : (asyncFunc, context, err, res) => {},
});

1.0.6

5 years ago

1.0.5

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago