引子

简单的程序,不许要考虑通信问题,在一个进程中函数调用即可满足程序功能的分治工作,

但是当程序规模达到一定程序之后, 就必须将程序划分为独立的逻辑体, 逻辑体之间需要进行通信。

本文列举程序通信方式,从微观到宏观。

事件

通过事件,可以将单线程的程序,做好逻辑切分的情况下,产生通信过程,同时保持逻辑解耦。

JS - DOM标准

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/EventTarget

EventTarget 的 addEventListener 方法添加事件, dispatchEvent 分发事件。
class MyEventTarget extends EventTarget {constructor(mySecret) {super();this._secret = mySecret;}get secret() { return this._secret; }
};let myEventTarget = new MyEventTarget(5);
let value = myEventTarget.secret;  // == 5
myEventTarget.addEventListener("foo", function(e) {this._secret = e.detail;
});let event = new CustomEvent("foo", { detail: 7 });
myEventTarget.dispatchEvent(event);
let newValue = myEventTarget.secret; // == 7

标准:

https://dom.spec.whatwg.org/#dom-eventtarget-eventtarget

target = new EventTarget();

Creates a new EventTarget object, which can be used by developers to dispatch and listen for events.

target . addEventListener(type, callback [, options])

Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched.

The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options’s capture.

When set to true, options’s capture prevents callback from being invoked when the event’s eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event’s eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event’s eventPhase attribute value is AT_TARGET.

When set to true, options’s passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in §2.8 Observing event listeners.

When set to true, options’s once indicates that the callback will only be invoked once after which the event listener will be removed.

The event listener is appended to target’s event listener list and is not appended if it has the same type, callback, and capture.

target . removeEventListener(type, callback [, options])

Removes the event listener in target’s event listener list with the same type, callback, and options.

target . dispatchEvent(event)

Dispatches a synthetic event event to target and returns true if either event’s cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise.

JS - commonjs标准

http://javascript.ruanyifeng.com/nodejs/events.html

const EventEmitter = require('events');class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter();
myEmitter.on('event', () => {console.log('an event occurred!');
});
myEmitter.emit('event');

标准:

https://nodejs.org/api/events.html#events_class_eventemitter

Much of the Node.js core API is built around an idiomatic asynchronous event-driven architecture in which certain kinds of objects (called "emitters") emit named events that cause Function objects ("listeners") to be called.

For instance: a net.Server object emits an event each time a peer connects to it; a fs.ReadStream emits an event when the file is opened; a stream emits an event whenever data is available to be read.

All objects that emit events are instances of the EventEmitter class. These objects expose an eventEmitter.on() function that allows one or more functions to be attached to named events emitted by the object. Typically, event names are camel-cased strings but any valid JavaScript property key can be used.

When the EventEmitter object emits an event, all of the functions attached to that specific event are called synchronously. Any values returned by the called listeners are ignored and will be discarded.

The following example shows a simple EventEmitter instance with a single listener. The eventEmitter.on() method is used to register listeners, while the eventEmitter.emit() method is used to trigger the event.

Spring - 注解

https://www.dev2qa.com/spring-event-publisher-listener-example/

Spring Event Publisher / Listener

Vue.js -- EventBUS

借助Vue API

https://alligator.io/vuejs/global-event-bus/

event-bus.js

import Vue from 'vue';
export const EventBus = new Vue();

linstener

// Import the EventBus.
import { EventBus } from './event-bus.js';// Listen for the i-got-clicked event and its payload.
EventBus.$on('i-got-clicked', clickCount => {console.log(`Oh, that's nice. It's gotten ${clickCount} clicks! :)`)
});

publisher

// Import the EventBus we just created.
import { EventBus } from './event-bus.js';// The event handler function.
const clickHandler = function(clickCount) {console.log(`Oh, that's nice. It's gotten ${clickCount} clicks! :)`)
}// Listen to the event.
EventBus.$on('i-got-clicked', clickHandler);// Stop listening.
EventBus.$off('i-got-clicked', clickHandler);

Vue API

https://cn.vuejs.org/v2/api/#%E5%AE%9E%E4%BE%8B%E6%96%B9%E6%B3%95-%E4%BA%8B%E4%BB%B6

  • 实例方法 / 事件

    • vm.$on
    • vm.$once
    • vm.$off
    • vm.$emit

这种用法有点hacker味道, 非Vue的原本设计。

所以有人专门为Vue实现了 EventBus 库。

Vue-Event

https://github.com/cklmercer/vue-events

import Vue from 'vue'
import VueEvents from 'vue-events'
Vue.use(VueEvents)

new Vue({data() {return {eventData: {foo: 'baz'}}},mounted() {this.$events.fire('testEvent', this.eventData);this.$events.emit('testEvent', this.eventData);this.$events.$emit('testEvent', this.eventData);}})

new Vue({mounted() {this.$events.on('testEvent', eventData => console.log(eventData));},beforeDestroy() {this.$events.$off('testEvent')this.$events.off('testEvent')this.$events.remove('testEvent')}
})

Vue-Bus

https://github.com/yangmingshan/vue-bus

// ...
created() {this.$bus.on('add-todo', this.addTodo);this.$bus.once('once', () => console.log('This listener will only fire once'));
},
beforeDestroy() {this.$bus.off('add-todo', this.addTodo);
},
methods: {addTodo(newTodo) {this.todos.push(newTodo);}
}

// ...
methods: {addTodo() {this.$bus.emit('add-todo', { text: this.newTodoText });this.$bus.emit('once');this.newTodoText = '';}
}

EventBus

https://github.com/google/guava/wiki/EventBusExplained

EventBus allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other). It is designed exclusively to replace traditional Java in-process event distribution using explicit registration. It is not a general-purpose publish-subscribe system, nor is it intended for interprocess communication.

he EventBus system and code use the following terms to discuss event distribution:

Event Any object that may be posted to a bus.
Subscribing The act of registering a listener with an EventBus, so that its handler methods will receive events.
Listener An object that wishes to receive events, by exposing handler methods.
Handler method A public method that the EventBus should use to deliver posted events. Handler methods are marked by the @Subscribe annotation.
Posting an event Making the event available to any listeners through the EventBus.

https://www.jianshu.com/p/f9ae5691e1bb

EventBus能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分离事件发送方和接收方(也就是解耦的意思),能避免复杂和容易出错的依赖性和生命周期问题。

三要素

  • Event 事件。它可以是任意类型。
  • Subscriber 事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
  • Publisher 事件的发布者。我们可以在任意线程里发布事件,一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

http://greenrobot.org/eventbus/

EventBus is an open-source library for Android and Java using the publisher/subscriber pattern for loose coupling. EventBus enables central communication to decoupled classes with just a few lines of code – simplifying the code, removing dependencies, and speeding up app development.

Your benefits using EventBus: It…

  • simplifies the communication between components
  • decouples event senders and receivers
  • performs well with UI artifacts (e.g. Activities, Fragments) and background threads
  • avoids complex and error-prone dependencies and life cycle issues
  • is fast; specifically optimized for high performance
  • is tiny (<50k jar)
  • is proven in practice by apps with 100,000,000+ installs
  • has advanced features like delivery threads, subscriber priorities, etc.

事件模式(发布、订阅)

https://www.zhihu.com/question/23486749

作者:无邪气
链接:https://www.zhihu.com/question/23486749/answer/314072549
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发布订阅模式属于广义上的观察者模式

发布订阅模式是最常用的一种观察者模式的实现,并且从解耦和重用角度来看,更优于典型的观察者模式

发布订阅模式多了个事件通道

在观察者模式中,观察者需要直接订阅目标事件;在目标发出内容改变的事件后,直接接收事件并作出响应

 ╭─────────────╮  Fire Event  ╭──────────────╮│             │─────────────>│              ││   Subject   │              │   Observer   ││             │<─────────────│              │╰─────────────╯  Subscribe   ╰──────────────╯

在发布订阅模式中,发布者和订阅者之间多了一个发布通道;一方面从发布者接收事件,另一方面向订阅者发布事件;订阅者需要从事件通道订阅事件

以此避免发布者和订阅者之间产生依赖关系

 ╭─────────────╮                 ╭───────────────╮   Fire Event   ╭──────────────╮│             │  Publish Event  │               │───────────────>│              ││  Publisher  │────────────────>│ Event Channel │                │  Subscriber  ││             │                 │               │<───────────────│              │╰─────────────╯                 ╰───────────────╯    Subscribe   ╰──────────────╯

作者:我曾跨过山和大海
链接:https://www.zhihu.com/question/23486749/answer/186049081
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

订阅/发布 模式重点是广播外的消息,这个模式并不关心谁接收事件,只管发送事件。

Let’s talk about two concepts that seem similar: the Observer pattern and the Pub-sub pattern.

Observer pattern

This is a pattern of development in which your class or primary object (known as the Observable) notifies other interested classes or objects (known as Observers) with relevant information (events).

Pub-sub pattern

The objective of the pub-sub pattern is exactly the same as the Observer pattern viz. you want some other class to know of certain events taking place.

There’s an important semantic difference between the Observer and Pub-sub patterns though: in the pub-sub pattern the focus is on “broadcasting” messages outside. The Observable here doesn’t want to know who the events are going out to, just that they’ve gone out. In other words the Observable (a.k.a Publisher) doesn’t want to know who the Observers (a.k.a Subscribers) are.

https://www.cnblogs.com/lovesong/p/5272752.html

var pubsub = {};
(function(myObject) {// Storage for topics that can be broadcast// or listened tovar topics = {};// An topic identifiervar subUid = -1;// Publish or broadcast events of interest// with a specific topic name and arguments// such as the data to pass alongmyObject.publish = function( topic, args ) {if ( !topics[topic] ) {return false;}var subscribers = topics[topic],len = subscribers ? subscribers.length : 0;while (len--) {subscribers[len].func( topic, args );}return this;};// Subscribe to events of interest// with a specific topic name and a// callback function, to be executed// when the topic/event is observedmyObject.subscribe = function( topic, func ) {if (!topics[topic]) {topics[topic] = [];}var token = ( ++subUid ).toString();topics[topic].push({token: token,func: func});return token;};// Unsubscribe from a specific// topic, based on a tokenized reference// to the subscriptionmyObject.unsubscribe = function( token ) {for ( var m in topics ) {if ( topics[m] ) {for ( var i = 0, j = topics[m].length; i < j; i++ ) {if ( topics[m][i].token === token ) {topics[m].splice( i, 1 );return token;}}}}return this;};
}( pubsub ));

进程间通信-DBus

https://www.freedesktop.org/wiki/Software/dbus/

D-Bus is a message bus system, a simple way for applications to talk to one another. In addition to interprocess communication, D-Bus helps coordinate process lifecycle; it makes it simple and reliable to code a "single instance" application or daemon, and to launch applications and daemons on demand when their services are needed.

D-Bus supplies both a system daemon (for events such as "new hardware device added" or "printer queue changed") and a per-user-login-session daemon (for general IPC needs among user applications). Also, the message bus is built on top of a general one-to-one message passing framework, which can be used by any two apps to communicate directly (without going through the message bus daemon). Currently the communicating applications are on one computer, or through unencrypted TCP/IP suitable for use behind a firewall with shared NFS home directories. (Help wanted with better remote transports - the transport mechanism is well-abstracted and extensible.)

The dbus low-level API reference implementation and the D-Bus protocol have been heavily tested in the real world over several years, and are now "set in stone." Future changes will either be compatible or versioned appropriately.

https://www.ibm.com/developerworks/cn/linux/l-dbus.html

D-BUS 本质上是 进程间通信(inter-process communication)(IPC)的一个实现。不过,有一些 特性使得 D-BUS 远远不是“只是另一个 IPC 实现”。有很多不同的 IPC 实现,因为每一个都定位于解决 特定的明确定义的问题。CORBA 是用于面向对象编程中复杂的 IPC 的一个强大的解决方案。DCOP 是一个 较轻量级的 IPC 框架,功能较少,但是可以很好地集成到 K 桌面环境中。SOAP 和 XML-RPC 设计用于 Web 服务,因而使用 HTTP 作为其传输协议。D-BUS 设计用于桌面应用程序和 OS 通信。

网络间通信-RabbitMQ

http://www.rabbitmq.com/#features

RabbitMQ is the most widely deployed open source message broker.

With more than 35,000 production deployments of RabbitMQ world-wide at small startups and large enterprises, RabbitMQ is the most popular open source message broker.

RabbitMQ is lightweight and easy to deploy on premises and in the cloud. It supports multiple messaging protocols. RabbitMQ can be deployed in distributed and federated configurations to meet high-scale, high-availability requirements.

http://www.rabbitmq.com/getstarted.html

RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as a post office: when you put the mail that you want posting in a post box, you can be sure that Mr. or Ms. Mailperson will eventually deliver the mail to your recipient. In this analogy, RabbitMQ is a post box, a post office and a postman.

The major difference between RabbitMQ and the post office is that it doesn't deal with paper, instead it accepts, stores and forwards binary blobs of data ‒ messages.

Introduction

Prerequisites

This tutorial assumes RabbitMQ is installed and running on localhost on standard port (5672). In case you use a different host, port or credentials, connections settings would require adjusting.

Where to get help

If you're having trouble going through this tutorial you can contact us through the mailing list.

RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as a post office: when you put the mail that you want posting in a post box, you can be sure that Mr. or Ms. Mailperson will eventually deliver the mail to your recipient. In this analogy, RabbitMQ is a post box, a post office and a postman.

The major difference between RabbitMQ and the post office is that it doesn't deal with paper, instead it accepts, stores and forwards binary blobs of data ‒ messages.

RabbitMQ, and messaging in general, uses some jargon.

  • Producing means nothing more than sending. A program that sends messages is a producer :

  • A queue is the name for a post box which lives inside RabbitMQ. Although messages flow through RabbitMQ and your applications, they can only be stored inside a queue. A queue is only bound by the host's memory & disk limits, it's essentially a large message buffer. Many producers can send messages that go to one queue, and many consumers can try to receive data from one queue. This is how we represent a queue:

  • Consuming has a similar meaning to receiving. A consumer is a program that mostly waits to receive messages:

Note that the producer, consumer, and broker do not have to reside on the same host; indeed in most applications they don't.

"Hello World"

(using the amqp.node client)

In this part of the tutorial we'll write two small programs in Javascript; a producer that sends a single message, and a consumer that receives messages and prints them out. We'll gloss over some of the detail in the amqp.node API, concentrating on this very simple thing just to get started. It's a "Hello World" of messaging.

In the diagram below, "P" is our producer and "C" is our consumer. The box in the middle is a queue - a message buffer that RabbitMQ keeps on behalf of the consumer.

https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/javascript-nodejs/src/receive.js

#!/usr/bin/env nodevar amqp = require('amqplib/callback_api');amqp.connect('amqp://localhost', function(err, conn) {conn.createChannel(function(err, ch) {var q = 'hello';ch.assertQueue(q, {durable: false});console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", q);ch.consume(q, function(msg) {console.log(" [x] Received %s", msg.content.toString());}, {noAck: true});});
});

#!/usr/bin/env nodevar amqp = require('amqplib/callback_api');amqp.connect('amqp://localhost', function(err, conn) {conn.createChannel(function(err, ch) {var q = 'hello';var msg = 'Hello World!';ch.assertQueue(q, {durable: false});ch.sendToQueue(q, Buffer.from(msg));console.log(" [x] Sent %s", msg);});setTimeout(function() { conn.close(); process.exit(0) }, 500);
});

转载于:https://www.cnblogs.com/lightsong/p/9551761.html

程序组件通信方案集锦相关推荐

  1. 微信小程序-------全局通信方案mobx

    微信小程序-------全局通信方案mobx 微信小程序本身并没有提供类似于vue中的vuex或者React里的Redux这样的全局通信方案,只在组件中有behaviors这样的属性共享机制,用起来也 ...

  2. Vue 非父子组件通信方案

    Vue 非父子组件通信方案 概述 在 Vue 中模块间的通信很普遍 如果是单纯的父子组件间传递信息,父组件可以使用 props 将数据向下传递到子组件,而在子组件中可以使用 events (父组件需要 ...

  3. 微信小程序组件通信入门及组件生命周期函数

    组件生命周期函数链接地址:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.h ...

  4. 支付宝小程序组件通信

    最近在公司接手支付宝小程序,虽然有微信小程序的开发经验,但是在部分细节上支付宝与微信还有差异.今天简单的介绍支付宝小程序中如何进行组件传值.本文用页面到组件传值说明嵌套组件传值的方式,即页面到组件 = ...

  5. 前端Vue入门-day04-用vue实现组件通信

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 组件的三大组成部分 注意点说明 组件的样式冲突 scoped data 是一个函数 组件通信 什么是组 ...

  6. 组件生命周期管理和通信方案

    随着移动互联网的快速发展,项目的迭代速度越来越快,需求改变越来越频繁,传统开发方式的工程所面临的一些,如代码耦合严重.维护效率低.开发不够敏捷等问题就凸现了出来.于是越来越多的公司开始推行" ...

  7. 微信小程序组件间通信(二)

    2019独角兽企业重金招聘Python工程师标准>>> 一.微信小程序中通过事件,实现子组件向父组件中传递数据或操作 注:子组件向父组件中传递通过事件传递操作 通过事件参数对象det ...

  8. 小程序使用vant-dialog组件内容出不来_微信官方小程序同构新方案Kbone全解析

    导语 | 本文是Kbone作者june在云加社区微信群中的分享整理总结而成(编辑:尾尾).同时,june将出席11月16日的TWeb腾讯前端技术大会,欢迎现场交流. 大家好,我是来自腾讯微信小程序团队 ...

  9. 微信小程序组件、路由、组件通信、侦听器

    一.微信小程序组件 组件就是小程序页面的组成结构,与html在web网页开发中的作用一样,铺设页面.可以参考其他UI库,像elementUI,vantUI组件 组件是视图层的基本组成单元. 组件自带一 ...

最新文章

  1. Java生成pdf设置两行页脚_Itextpdf 5 html生成pdf 页眉页脚
  2. Sql Server 连接池
  3. 前端用Sass实现星级评定效果,简单快捷实现星级切换。
  4. node.js Error: connect EMFILE 或者 getaddrinfo ENOTFOUND
  5. 有意思的逻辑思维题(三)(hdu2211,蓝桥杯蚂蚁感冒)
  6. Java面向对象的程序设计
  7. mnist数据集读取并保存为Numpy数组
  8. 前端代码异常日志收集与监控
  9. 计算机主机特点,计算机的五大特点是什么
  10. CPU+GPU异构集群搭建的总结说明
  11. android无线充电技术,无线充电Qi通信协议分析,充电qi通信协议
  12. cesium 经纬度绘制点_Cesium搜索经纬度并标点
  13. java 美元符号_使用单个美元符号“$”作为java类名称的任何风险?
  14. 为村上隆直播做同传的火山翻译:成立仅3年,拿下5项世界冠军
  15. 初中英语多词性单词怎么办_初中英语单词按词性分类表
  16. Gif动态图片怎么做?如何快速生成gif动图?
  17. HDU4730 We Love MOE Girls
  18. 百度谷歌一起搜 - 百Google度 - Chrome插件
  19. adb安装应用失败,错误码整理
  20. 基于h5的航空订票系统的设计与实现

热门文章

  1. SQL Server 2008 R2 系统配置检查器的检查参数和妨碍性问题的解决办法
  2. vue2.0 新手教程(一)
  3. android:textAppearance
  4. Segmentation fault (core dumped)
  5. Spring 开启Annotation context:annotation-config 和 context:component-scan诠释及区别
  6. 如何用DELPHI区分彩色图和黑白图(多色与单色)??
  7. 我的家乡-客家小山村
  8. MacBook file storage 256g is ok
  9. xjtlu mac mail 绑定
  10. 如果不知道做什么,那应该做什么呢?