-
Notifications
You must be signed in to change notification settings - Fork 68
/
pubsub.js
102 lines (91 loc) · 3 KB
/
pubsub.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/** @license MIT License (c) copyright B Cavalier & J Hann */
/**
* wire/dojo/pubsub plugin
* wire plugin that sets up subscriptions and topics to be published after
* functions are invoked, and disconnect them when an object is destroyed.
* This implementation uses dojo.publish, dojo.subscribe and dojo.unsubscribe
* to do the work of connecting and disconnecting event handlers.
*
* wire is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
define(['dojo', 'aop', 'dojo/_base/connect'], function(pubsub, aop) {
return {
wire$plugin: function pubsubPlugin(ready, destroyed /*, options */) {
var destroyHandlers = [];
/**
* Add after advice to publish the result of target[method]
* @param target {Object} target object
* @param method {String} method name to which to apply advice
* @param topic {String} dojo.publish topic on which to publish the result
*/
function addPublishAdvice(target, method, topic) {
return aop.after(target, method, function(result) {
pubsub.publish(topic, [result]);
});
}
/**
* Proxies methods on target so that they publish topics after
* being invoked. The payload of a topic will be the return
* value of the method that triggered it.
* @param target {Object} object whose methods should be proxied
* @param publish {Object} hash of method names to topics each should publish
*/
function proxyPublish(target, publish) {
var remove;
for(var method in publish) {
if(typeof target[method] == 'function') {
// Add after advice and save remove function to remove
// advice when this context is destroyed
remove = addPublishAdvice(target, method, publish[method]);
destroyHandlers.push(remove);
}
}
}
function subscribeTarget(target, subscriptions) {
var subscribeHandles = [];
for(var topic in subscriptions) {
var method = subscriptions[topic];
if(typeof target[method] == 'function') {
subscribeHandles.push(pubsub.subscribe(topic, target, method));
}
}
if(subscribeHandles.length > 0) {
destroyHandlers.push(function() {
unsubscribeTarget(subscribeHandles);
});
}
}
function unsubscribeTarget(handles) {
for (var i = handles.length - 1; i >= 0; --i){
pubsub.unsubscribe(handles[i]);
}
}
// When the context is destroyed, remove all publish and
// subscribe hooks created in this context
destroyed.then(function onContextDestroy() {
for (var i = destroyHandlers.length - 1; i >= 0; --i){
destroyHandlers[i]();
}
});
return {
facets: {
publish: {
ready: function(promise, facet, wire) {
proxyPublish(facet.target, facet.options);
promise.resolve();
}
},
subscribe: {
ready: function(promise, facet, wire) {
subscribeTarget(facet.target, facet.options);
promise.resolve();
}
}
}
}
}
};
});