msg-q@0.1.0

Batched MessageQueue

/* tslint:disable:no-console no-bitwise */

import { MessageQueue } from 'msg-q';

// ---------------------------------- native
const realModules = {
  module1: {
    method1(seq) {
      console.info('[remote] module1 method1 implementation', seq);
    },
  },

  module2: {
    method2(seq, callback) {
      console.info('[remote] module2 method2 implementation', seq);
      callback(seq + 1);
    },
  },

  timer: {
    setTimeout(m, f) {
      window.setTimeout(f, m);
    },
  },
};

const moduleInfo = {};

Object.keys(realModules).forEach(m => {
  moduleInfo[m] = Object.keys(realModules[m]);
});

function nativeFlushQueueImmediate(queue) {
  if (!queue) {
    return;
  }
  const calls = queue[0].length;
  for (let i = 0; i < calls; i++) {
    const moduleName = queue[0][i];
    const method = queue[1][i];
    const params = queue[2][i];
    let callbacks = queue[3][i];
    while (callbacks) {
      ((num) => {
        const index = params.length - num;
        const callId = params[index];
        params[index] = (...args) => {
          // native call js engine directly
          nativeFlushQueueImmediate((window as any).__batchedBridge.invokeCallbackAndReturnFlushedQueue(callId, args));
        };
      })(callbacks);
      callbacks--;
    }

    try {
      realModules[moduleName][method].apply(realModules[moduleName], params);
    } catch (e) {
      console.error(e);
    }
  }
}

// inject nativeFlushQueueImmediate
// pass moduleInfo to webview/jscore
(window as any).nativeFlushQueueImmediate = nativeFlushQueueImmediate;

// -------------------------------- webview/jscore

const mq = new MessageQueue();

// for native call
(window as any).__batchedBridge = mq;

// TODO clearTimeout
function setTimeout(f, m) {
  mq.rpc('timer', 'setTimeout', [m, f]);
}

const stubModules: any = {};

Object.keys(moduleInfo).forEach(m => {
  const methods = {};
  moduleInfo[m].forEach((f) => {
    methods[f] = function run(...args) {
      return mq.rpc(m, f, args);
    };
  });
  stubModules[m] = methods;
});

// 1 sync
stubModules.module1.method1(1);

// 2 callback
stubModules.module2.method2(2, (seq) => {
  console.info('[stub] receive from callback', seq);
});

// 3 async
setTimeout(() => {
  stubModules.module1.method1(10);
  stubModules.module2.method2(20, (seq) => {
    console.info('[stub] receive from async callback', seq);
  });
}, 100);

nativeFlushQueueImmediate(mq.flushedQueue());
Fork me on GitHub