Code Monkey home page Code Monkey logo

async-message's Introduction

async-message

使用一个统一的API调用其他窗口/线程的方法,像调用一个异步函数一样简单

npm version npm bundle size (minified)

# use npm
npm install --save async-message
# use yarn
yarn add async-message
# use pnpm
pnpm install async-message

特性

  • 多平台支持,web / node / electron
  • 接口适配,自定义不同场景
  • 完美支持Typescript
  • 自定义序列化/反序列化插件

快速开始

例子

// master.ts
import { caller } from 'async-message';
import { WorkerChannel } from 'async-message/web';
import type { Counter } from './workers/counter';

const worker = new Worker('./workers/counter');
const channel = new WorkerChannel(worker);
const counter = caller<Counter>(channel);

const count = await counter.getCount();
console.log('current cout:', count);

const nextCount = await counter.increment();
console.log('next count:', nextCount);
// workers/counter.ts
import { producer } from 'async-message';
import { WorkerChannel } from 'async-message/web';

const channel = new WorkerChannel();

const counter = {
  count: 0,
  getCount() {
    return this.count;
  },
  increment() {
    return ++this.count;
  },
  decrement() {
    return --this.count;
  },
}

producer(channel, counter);

export type Counter = typeof counter;

在web worker例子中,主线程调用工作线程导出的counter

  • caller通过channel发送消息给worker
  • worker里通过channel接受到caller的消息,并执行counter的方法
  • 方法执行结果再通过channel发送给caller,完成一次调用

channel

负责发送消息 / 接受消息 / 广播消息channel继承emitter

caller(channel, timeout)

负责通过channel代理对worker中producer目标的调用,所有方法均返回一个promise

producer(channel, target)

负责通过channel导出target给其他caller调用

平台

Web

import { WorkerChannel, WindowChannel } from 'async-message/web';

// for worker 主线程
new WorkerChannel(new Worker('./worker.js'));
// for worker 工作线程
new WorkerChannel();

// for shared worker 主线程
new WorkerChannel(new SharedWorker('./worker.js'));
// for shared worker 工作线程
new WorkerChannel();

// for iframe 父窗口
const iframe = document.querySelector('iframe');
new WindowChannel(iframe.contentWindow, 'https://xxx.xx');
// for iframe 子窗口
new WindowChannel('https://xxx.xx');

// for window 父窗口
const win = window.open('https://xxx.xx');
new WindowChannel(win, 'https://xxx.xx');
// for window 子窗口
new WindowChannel('https://xxx.xx');

Node

import { WorkerChannel } from 'async-message/node';
import { Worker } from 'worker_threads';

// for worker 主线程
new WorkerChannel(new Worker('./worker.js'));
// for worker 工作线程
new WorkerChannel();

Electron

import { IpcChannel } from 'async-message/electron';

// for main 主线程
new IpcChannel();
// for renderer 渲染线程
new IpcChannel();

序列化

回调函数

数据传递的时候函数无法被序列化,需要一些额外的手段来传递回调函数,通过callbackSerializer赋予channel序列化/反序列化函数的能力

需要在传递函数的时候注册用registerCallback包裹,注销的时候用unregisterCallback包裹,否则此函数会常驻于内存

// master.ts
import { caller } from 'async-message';
import { WorkerChannel } from 'async-message/web';
import { callbackSerializer, registerCallback, unregisterCallback } from 'async-message/serializer'
import type { Target } from './workers/target';

const worker = new Worker('./workers/target');

const channel = new WorkerChannel(worker);
channel.registerSerializer(callbackSerializer); // 这一步是必须的

const target = caller<Target>(channel);

const callback = () => {};

await target.addEventListener('test', registerCallback(callback));

await target.removeEventListener('test', unregisterCallback(callback));
// workers/target.ts
import { producer } from 'async-message';
import { WorkerChannel } from 'async-message/web';
import { callbackSerializer } from 'async-message/serializer'

const channel = new WorkerChannel();
channel.registerSerializer(callbackSerializer); // 这一步是必须的

const target = {
  addEventListener(type: string, listener: (...args: any[]) => void) {
    // do something
  },
  removeEventListener(type: string, listener: (...args: any[]) => void) {
    // do something
  }
}

producer(channel, target);

export type Target = typeof counter;

callbackSerializer会遍历所有数据字段,如果传递的数据量太大,请自定义serializer

高级用法

自定义channel

import { Channel, Message } from 'async-message';

class MyChannel extends Channel {
  postMessage(message: Message) {
    // do something
  }
}

自定义serializer

import { Serializer, Channel } from 'async-message'

const mySerializer: Serializer = {
  onRegister(channel: Channel) {
    // do something
  },
  onUnregister(channel: Channel) {
    // do something
  },
  serialize(value: unknown, fallback: (value: unknown) => any, poster: Poster) {
    // do something
  },
  deserialize(value: unknown, fallback: (value: unknown) => any, poster: Poster) {
    // do something
  }
}

async-message's People

Contributors

jumperchuck avatar

Stargazers

 avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.