on.js
3.63 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
var Gun = require('./index');
Gun.chain.on = function(tag, arg, eas, as){
var gun = this, at = gun._, tmp, act, off;
if(typeof tag === 'string'){
if(!arg){ return at.on(tag) }
act = at.on(tag, arg, eas || at, as);
if(eas && eas.$){
(eas.subs || (eas.subs = [])).push(act);
}
return gun;
}
var opt = arg;
opt = (true === opt)? {change: true} : opt || {};
opt.at = at;
opt.ok = tag;
//opt.last = {};
gun.get(ok, opt); // TODO: PERF! Event listener leak!!!?
return gun;
}
function ok(msg, ev){ var opt = this;
var gun = msg.$, at = (gun||{})._ || {}, data = at.put || msg.put, cat = opt.at, tmp;
if(u === data){
return;
}
if(tmp = msg.$$){
tmp = (msg.$$._);
if(u === tmp.put){
return;
}
data = tmp.put;
}
if(opt.change){ // TODO: BUG? Move above the undef checks?
data = msg.put;
}
// DEDUPLICATE // TODO: NEEDS WORK! BAD PROTOTYPE
//if(tmp.put === data && tmp.get === id && !Gun.node.soul(data)){ return }
//tmp.put = data;
//tmp.get = id;
// DEDUPLICATE // TODO: NEEDS WORK! BAD PROTOTYPE
//at.last = data;
if(opt.as){
opt.ok.call(opt.as, msg, ev);
} else {
opt.ok.call(gun, data, msg.get, msg, ev);
}
}
Gun.chain.val = function(cb, opt){
Gun.log.once("onceval", "Future Breaking API Change: .val -> .once, apologies unexpected.");
return this.once(cb, opt);
}
Gun.chain.once = function(cb, opt){
var gun = this, at = gun._, data = at.put;
if(0 < at.ack && u !== data){
(cb || noop).call(gun, data, at.get);
return gun;
}
if(cb){
(opt = opt || {}).ok = cb;
opt.at = at;
opt.out = {'#': Gun.text.random(9)};
gun.get(val, {as: opt});
opt.async = true; //opt.async = at.stun? 1 : true;
} else {
Gun.log.once("valonce", "Chainable val is experimental, its behavior and API may change moving forward. Please play with it and report bugs and ideas on how to improve it.");
var chain = gun.chain();
chain._.nix = gun.once(function(){
chain._.on('in', gun._);
});
return chain;
}
return gun;
}
function val(msg, eve, to){
if(!msg.$){ eve.off(); return }
var opt = this.as, cat = opt.at, gun = msg.$, at = gun._, data = at.put || msg.put, link, tmp;
if(tmp = msg.$$){
link = tmp = (msg.$$._);
if(u !== link.put){
data = link.put;
}
}
if((tmp = eve.wait) && (tmp = tmp[at.id])){ clearTimeout(tmp) }
eve.ack = (eve.ack||0)+1;
if(!to && u === data && eve.ack <= (opt.acks || Object.keys(at.root.opt.peers).length)){ return }
if((!to && (u === data || at.soul || at.link || (link && !(0 < link.ack))))
|| (u === data && (tmp = Object.keys(at.root.opt.peers).length) && (!to && (link||at).ack < tmp))){
tmp = (eve.wait = {})[at.id] = setTimeout(function(){
val.call({as:opt}, msg, eve, tmp || 1);
}, opt.wait || 99);
return;
}
if(link && u === link.put && (tmp = rel.is(data))){ data = Gun.node.ify({}, tmp) }
eve.rid? eve.rid(msg) : eve.off();
opt.ok.call(gun || opt.$, data, msg.get);
}
Gun.chain.off = function(){
// make off more aggressive. Warning, it might backfire!
var gun = this, at = gun._, tmp;
var cat = at.back;
if(!cat){ return }
at.ack = 0; // so can resubscribe.
if(tmp = cat.next){
if(tmp[at.get]){
obj_del(tmp, at.get);
} else {
}
}
if(tmp = cat.ask){
obj_del(tmp, at.get);
}
if(tmp = cat.put){
obj_del(tmp, at.get);
}
if(tmp = at.soul){
obj_del(cat.root.graph, tmp);
}
if(tmp = at.map){
obj_map(tmp, function(at){
if(at.link){
cat.root.$.get(at.link).off();
}
});
}
if(tmp = at.next){
obj_map(tmp, function(neat){
neat.$.off();
});
}
at.on('off', {});
return gun;
}
var obj = Gun.obj, obj_map = obj.map, obj_has = obj.has, obj_del = obj.del, obj_to = obj.to;
var rel = Gun.val.link;
var empty = {}, noop = function(){}, u;