Have ideas to improve npm?Join in the discussion! ¬Ľ

    batching

    1.0.6¬†‚Äʬ†Public¬†‚Äʬ†Published

    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

    Param Type Default Description
    options object
    [options.logStart] boolean | function false interface : (asyncFunc : function, context : object) => void
    [options.logFinish] boolean | function false interface : (asyncFunc : function, context : object, err : object, res : any) => void
    [options.isArgsEqual] function _.isEqual arguments comparator
    [options.isThisEqual] function _.isEqual this 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

    Param Type
    asyncFunc function
    [thisArg] any

    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

    Param Type
    asyncFunc function
    args array
    thisArg object

    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

    Param Type Description
    options boolean | object turn 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) => {},
    });

    Install

    npm i batching

    DownloadsWeekly Downloads

    14

    Version

    1.0.6

    License

    ISC

    Unpacked Size

    19.6 kB

    Total Files

    4

    Last publish

    Collaborators

    • avatar