<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://vrpc.io/blog</id>
    <title>VRPC blog</title>
    <updated>2026-10-11T12:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://vrpc.io/blog"/>
    <subtitle>VRPC Blog</subtitle>
    <icon>https://vrpc.io/favicon.ico</icon>
    <rights>Copyright © 2018 Heisenware GmbH</rights>
    <entry>
        <title type="html"><![CDATA[Events that scale]]></title>
        <id>https://vrpc.io/blog/events-that-scale</id>
        <link href="https://vrpc.io/blog/events-that-scale"/>
        <updated>2026-10-11T12:00:00.000Z</updated>
        <summary type="html"><![CDATA[VRPC 3.15 brings protocol 4. An event function runs once, however many clients listen - why that matters, and what else changed.]]></summary>
        <content type="html"><![CDATA[
<p><em><a class="" href="https://vrpc.io/blog/ein-handler-statt-1100">Auf Deutsch lesen</a></em></p>
<p>In an app on the Heisenware platform, a counter registered its event handler
again once a minute. Nothing in between knew it was the same listener. After 19 hours
the instance held 1,100 copies of one handler, and every pulse of the
counter went out 1,100 times.</p>
<p>VRPC 3.15 ends that for good. It brings protocol 4, and with it a simple
rule: <strong>an event function runs once, however many listen.</strong></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-vrpc-is">What VRPC is<a href="https://vrpc.io/blog/events-that-scale#what-vrpc-is" class="hash-link" aria-label="Direct link to What VRPC is" title="Direct link to What VRPC is" translate="no">​</a></h2>
<p>VRPC makes the classes of one program callable from others, as if they were
local. You register a class with an agent; any client - a backend service, a
browser, a device - creates instances of it, calls their functions and
listens to their events. Agents and clients only connect out to an MQTT
broker, so code behind a firewall is reachable, and there is no API layer to
write: the class is the contract.</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// on the Raspberry Pi in the kitchen</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token maybe-class-name">VrpcAdapter</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token maybe-class-name">VrpcAgent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'vrpc'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Sensor</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">/* read(), onReading(handler) */</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token maybe-class-name">VrpcAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Sensor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">VrpcAgent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">domain</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'home'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">agent</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'pi-kitchen'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">serve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// anywhere else: a backend, a browser</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token maybe-class-name">VrpcClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'vrpc'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> client </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">VrpcClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">domain</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'home'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">connect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> sensor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'kitchen'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> sensor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> sensor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">onReading</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">celsius</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> chart</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">celsius</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-registration-many-subscriptions">One registration, many subscriptions<a href="https://vrpc.io/blog/events-that-scale#one-registration-many-subscriptions" class="hash-link" aria-label="Direct link to One registration, many subscriptions" title="Direct link to One registration, many subscriptions" translate="no">​</a></h2>
<p>Before 3.15, every subscribing call reached the class's event function anew.
Ten browsers on one sensor meant ten listeners on it, and a client that
subscribed again after a hiccup added one more. Protocol 4 separates two
things:</p>
<ul>
<li class="">A <strong>registration</strong> is the one call of an event function, for one
instance, function and arguments. The agent makes it once.</li>
<li class="">A <strong>subscription</strong> is one listener's wish to receive those events.
Subscriptions are sets: declaring one again changes nothing.</li>
</ul>
<p>The agent hands every event of a registration to all of its subscriptions,
and releases the registration when the last subscription leaves. Ten
browsers on one sensor are one listener on the emitter, not ten - and the
counter from above holds exactly one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tell-vrpc-how-to-undo-it">Tell VRPC how to undo it<a href="https://vrpc.io/blog/events-that-scale#tell-vrpc-how-to-undo-it" class="hash-link" aria-label="Direct link to Tell VRPC how to undo it" title="Direct link to Tell VRPC how to undo it" translate="no">​</a></h2>
<p>An event function returns a registration object. It says how to release the
registration, and optionally how to greet a newcomer:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">onReading</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">_emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'reading'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token known-class-name class-name">Symbol</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">dispose</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">_emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">off</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'reading'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">greet</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token parameter">greeting</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">greeting</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">_reading</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p><code>[Symbol.dispose]</code> runs when the last subscriber leaves. <code>greet</code> runs for
every new subscriber, the first one included, so each one starts with the
current reading instead of waiting for the next change - however late it
joins.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ends-are-told-losses-heal">Ends are told, losses heal<a href="https://vrpc.io/blog/events-that-scale#ends-are-told-losses-heal" class="hash-link" aria-label="Direct link to Ends are told, losses heal" title="Direct link to Ends are told, losses heal" translate="no">​</a></h2>
<p>A registration can end: its instance is deleted, or the class ends it. Every
subscriber is told, and the client emits <code>ended</code> instead of calling the
handler again. When an agent goes offline, the client keeps its
subscriptions there and declares them again once the agent is back - it
emits <code>lost</code>, then <code>healed</code>, and nobody has to rebuild anything.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fewer-bytes-fewer-requests-fewer-surprises">Fewer bytes, fewer requests, fewer surprises<a href="https://vrpc.io/blog/events-that-scale#fewer-bytes-fewer-requests-fewer-surprises" class="hash-link" aria-label="Direct link to Fewer bytes, fewer requests, fewer surprises" title="Direct link to Fewer bytes, fewer requests, fewer surprises" translate="no">​</a></h2>
<ul>
<li class=""><strong>Answers carry only what a call yielded.</strong> They no longer echo the
arguments, which made a large argument cross the network twice.</li>
<li class=""><strong><code>callAll</code> selects instances.</strong> <code>instances: 'line-3*'</code> calls those alone,
in one request per agent however many instances it holds, and
<code>agent: 'edge-*'</code> asks all matching agents at once.</li>
<li class=""><strong>Only what a class publishes can be called.</strong> <code>emit</code> and private helpers
were reachable with a hand-made request; now they are not, and <code>@private</code>
in the JSDoc keeps a function inside as well.</li>
<li class=""><strong>Every request that reaches an agent is answered</strong>, and errors travel as
<code>{ message, cause }</code>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="written-down">Written down<a href="https://vrpc.io/blog/events-that-scale#written-down" class="hash-link" aria-label="Direct link to Written down" title="Direct link to Written down" translate="no">​</a></h2>
<p>Protocol 4 is specified rule by rule in the
<a class="" href="https://vrpc.io/docs/spec/protocol">protocol specification</a>: numbered rules, and tests
that name the rule they check. It binds every VRPC implementation. The C++,
Python and Arduino ports speak protocol 3 today, and that keeps working: a
3.15 agent serves older clients, and a 3.15 client talks to older agents.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it">Try it<a href="https://vrpc.io/blog/events-that-scale#try-it" class="hash-link" aria-label="Direct link to Try it" title="Direct link to Try it" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> vrpc@3.15</span><br></div></code></pre></div></div>
<p><a class="" href="https://vrpc.io/docs/getting-started">Getting started</a> takes ten minutes,
<a class="" href="https://vrpc.io/docs/concepts/events">Events</a> explains the model, and the
<a href="https://github.com/heisenware/vrpc-js/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="">changelog</a>
lists every change. If VRPC saves you some boilerplate, a
<a href="https://github.com/heisenware/vrpc-js" target="_blank" rel="noopener noreferrer" class="">star on GitHub</a> helps others find it.</p>]]></content>
        <author>
            <name>Dr. Burkhard Heisen</name>
            <uri>https://heisenware.com</uri>
        </author>
        <category label="Release" term="Release"/>
        <category label="Events" term="Events"/>
        <category label="Protocol" term="Protocol"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Ein Handler statt 1.100]]></title>
        <id>https://vrpc.io/blog/ein-handler-statt-1100</id>
        <link href="https://vrpc.io/blog/ein-handler-statt-1100"/>
        <updated>2026-10-11T11:59:00.000Z</updated>
        <summary type="html"><![CDATA[VRPC 3.15 bringt Protokoll 4. Eine Event-Funktion läuft jetzt genau einmal – egal, wie viele Clients sie abonnieren. Was dahintersteckt und was sich sonst noch ändert.]]></summary>
        <content type="html"><![CDATA[
<p><em><a class="" href="https://vrpc.io/blog/events-that-scale">Read in English</a></em></p>
<p>Ein Zähler in einer App auf der Heisenware-Plattform hat sich jede Minute neu
für sein Event registriert. Aufgefallen ist das niemandem – bis nach 19
Stunden 1.100 Kopien desselben Handlers an der Instanz hingen und jeder
einzelne Impuls 1.100-mal verschickt wurde.</p>
<p>Mit VRPC 3.15 ist damit Schluss. Das Release bringt Protokoll 4 und eine
einfache Regel: <strong>Eine Event-Funktion läuft genau einmal – egal, wie viele
Clients sie abonnieren.</strong></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vrpc-in-drei-sätzen">VRPC in drei Sätzen<a href="https://vrpc.io/blog/ein-handler-statt-1100#vrpc-in-drei-s%C3%A4tzen" class="hash-link" aria-label="Direct link to VRPC in drei Sätzen" title="Direct link to VRPC in drei Sätzen" translate="no">​</a></h2>
<p>Mit VRPC werden die Klassen eines Programms aus anderen Programmen heraus
aufgerufen, als wären sie lokal. Eine Klasse wird bei einem Agenten
registriert; Clients – ein Backend, ein Browser, ein Gerät – erzeugen davon
Instanzen, rufen Funktionen auf und abonnieren Events. Alle verbinden sich
nur ausgehend mit einem MQTT-Broker, deshalb ist auch Code hinter einer
Firewall erreichbar, und eine API-Schicht braucht es nicht: Die Klasse ist
die Schnittstelle.</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// läuft auf dem Raspberry Pi in der Küche</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token maybe-class-name">VrpcAdapter</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token maybe-class-name">VrpcAgent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'vrpc'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Sensor</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">/* read(), onReading(handler) */</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token maybe-class-name">VrpcAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Sensor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">VrpcAgent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">domain</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'home'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">agent</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'pi-kitchen'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">serve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// läuft überall sonst: im Backend, im Browser</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token maybe-class-name">VrpcClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'vrpc'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> client </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">VrpcClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">domain</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'home'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">connect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> sensor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'kitchen'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> sensor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> sensor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">onReading</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">celsius</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> chart</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">celsius</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="registrierung-und-subscription-sind-jetzt-zwei-dinge">Registrierung und Subscription sind jetzt zwei Dinge<a href="https://vrpc.io/blog/ein-handler-statt-1100#registrierung-und-subscription-sind-jetzt-zwei-dinge" class="hash-link" aria-label="Direct link to Registrierung und Subscription sind jetzt zwei Dinge" title="Direct link to Registrierung und Subscription sind jetzt zwei Dinge" translate="no">​</a></h2>
<p>Bisher landete jeder Aufruf, der ein Event abonnierte, direkt in der
Event-Funktion der Klasse. Zehn Browser am selben Sensor bedeuteten zehn
Listener, und jeder Client, der nach einem Verbindungsabbruch neu
abonnierte, legte noch einen drauf. Protokoll 4 trennt das sauber:</p>
<ul>
<li class="">Die <strong>Registrierung</strong> ist der Aufruf der Event-Funktion – pro Instanz,
Funktion und Argumenten genau einmal.</li>
<li class="">Eine <strong>Subscription</strong> steht für einen Client, der die Events bekommen
will. Wird doppelt abonniert, ändert sich nichts.</li>
</ul>
<p>Jedes Event wird vom Agenten an alle Subscriptions einer Registrierung
verteilt. Verschwindet die letzte Subscription, wird auch die Registrierung
freigegeben. Zehn Browser an einem Sensor ergeben damit einen Listener statt
zehn – und an dem Zähler von oben hängt genau einer.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="aufräumen-und-begrüßen">Aufräumen und begrüßen<a href="https://vrpc.io/blog/ein-handler-statt-1100#aufr%C3%A4umen-und-begr%C3%BC%C3%9Fen" class="hash-link" aria-label="Direct link to Aufräumen und begrüßen" title="Direct link to Aufräumen und begrüßen" translate="no">​</a></h2>
<p>Damit klar ist, wie eine Registrierung wieder abgebaut wird, gibt die
Event-Funktion ein Registrierungsobjekt zurück. Optional steht darin auch,
wie neue Abonnenten begrüßt werden:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">onReading</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">_emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'reading'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token known-class-name class-name">Symbol</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">dispose</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">_emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">off</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'reading'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">greet</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token parameter">greeting</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">greeting</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">_reading</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p><code>[Symbol.dispose]</code> wird aufgerufen, wenn die letzte Subscription weg ist.
<code>greet</code> läuft für jede neue Subscription, auch für die erste. So startet
jeder Client mit dem aktuellen Messwert und muss nicht auf die nächste
Änderung warten – auch wenn er erst Stunden später dazukommt.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="wenn-etwas-endet-oder-wegbricht">Wenn etwas endet oder wegbricht<a href="https://vrpc.io/blog/ein-handler-statt-1100#wenn-etwas-endet-oder-wegbricht" class="hash-link" aria-label="Direct link to Wenn etwas endet oder wegbricht" title="Direct link to Wenn etwas endet oder wegbricht" translate="no">​</a></h2>
<p>Endet eine Registrierung, weil die Instanz gelöscht wurde oder die Klasse
sie beendet, bekommen alle Abonnenten Bescheid: Der Client meldet <code>ended</code>,
und der Handler wird nicht mehr aufgerufen. Geht ein Agent offline, bleiben
die Subscriptions beim Client erhalten und werden von selbst neu angemeldet,
sobald der Agent wieder da ist (<code>lost</code>, danach <code>healed</code>). Neu aufgebaut
werden muss nichts.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="was-sich-sonst-noch-tut">Was sich sonst noch tut<a href="https://vrpc.io/blog/ein-handler-statt-1100#was-sich-sonst-noch-tut" class="hash-link" aria-label="Direct link to Was sich sonst noch tut" title="Direct link to Was sich sonst noch tut" translate="no">​</a></h2>
<ul>
<li class=""><strong>Schlankere Antworten:</strong> Eine Antwort enthält nur noch das Ergebnis. Die
Argumente werden nicht mehr zurückgeschickt; große Argumente gingen bisher
zweimal übers Netz.</li>
<li class=""><strong><code>callAll</code> mit Auswahl:</strong> Mit <code>instances: 'line-3*'</code> werden nur die
passenden Instanzen aufgerufen, mit einer einzigen Anfrage pro Agent.
<code>agent: 'edge-*'</code> fragt alle passenden Agenten gleichzeitig.</li>
<li class=""><strong>Aufrufbar ist nur, was veröffentlicht ist:</strong> <code>emit</code> und private
Hilfsfunktionen ließen sich bisher mit einer selbst gebauten Anfrage
erreichen. Das ist vorbei, und mit <code>@private</code> im JSDoc bleibt eine Funktion
ebenfalls intern.</li>
<li class=""><strong>Jede Anfrage wird beantwortet</strong>, und Fehler kommen einheitlich als
<code>{ message, cause }</code>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="schwarz-auf-weiß">Schwarz auf weiß<a href="https://vrpc.io/blog/ein-handler-statt-1100#schwarz-auf-wei%C3%9F" class="hash-link" aria-label="Direct link to Schwarz auf weiß" title="Direct link to Schwarz auf weiß" translate="no">​</a></h2>
<p>Protokoll 4 ist in der <a class="" href="https://vrpc.io/docs/spec/protocol">Protokollspezifikation</a> Regel
für Regel festgehalten – nummeriert, und jeder Test nennt die Regel, die er
prüft. Die Spezifikation gilt für alle VRPC-Implementierungen. Die
Portierungen für C++, Python und Arduino sprechen noch Protokoll 3, und das
funktioniert weiterhin: Ein Agent ab 3.15 bedient auch ältere Clients, und
umgekehrt.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ausprobieren">Ausprobieren<a href="https://vrpc.io/blog/ein-handler-statt-1100#ausprobieren" class="hash-link" aria-label="Direct link to Ausprobieren" title="Direct link to Ausprobieren" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> vrpc@3.15</span><br></div></code></pre></div></div>
<p>Die Dokumentation ist auf Englisch. Mit <a class="" href="https://vrpc.io/docs/getting-started">Getting started</a>
läuft das erste Beispiel in zehn Minuten, <a class="" href="https://vrpc.io/docs/concepts/events">Events</a>
erklärt das Modell, und im
<a href="https://github.com/heisenware/vrpc-js/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="">Changelog</a>
steht jede Änderung. Wenn dir VRPC Boilerplate erspart, freuen wir uns über
einen <a href="https://github.com/heisenware/vrpc-js" target="_blank" rel="noopener noreferrer" class="">Stern auf GitHub</a> – damit es
auch andere finden.</p>]]></content>
        <author>
            <name>Dr. Burkhard Heisen</name>
            <uri>https://heisenware.com</uri>
        </author>
        <category label="Release" term="Release"/>
        <category label="Events" term="Events"/>
        <category label="Protocol" term="Protocol"/>
        <category label="Deutsch" term="Deutsch"/>
    </entry>
</feed>