-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathmithril.computation.html
188 lines (171 loc) · 10.3 KB
/
mithril.computation.html
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<!doctype html>
<html>
<head>
<title>Mithril</title>
<link href="lib/prism/prism.css" rel="stylesheet" />
<link href="style.css" rel="stylesheet" />
</head>
<body>
<header>
<nav class="container">
<a href="index.html" class="logo"><span>○</span> Mithril</a>
<a href="getting-started.html">Guide</a>
<a href="mithril.html">API</a>
<a href="community.html">Community</a>
<a href="http://lhorie.github.io/mithril-blog">Blog</a>
<a href="mithril.min.zip">Download</a>
<a href="http://github.com/lhorie/mithril.js" target="_blank">Github</a>
</nav>
</header>
<main>
<section class="content">
<div class="container">
<div class="row">
<div class="col(3,3,12)">
<h2 id="api">API (v0.1.21)</h2>
<h3 id="core">Core</h3>
<ul>
<li><a href="mithril.html">m</a></li>
<li><a href="mithril.prop.html">m.prop</a></li>
<li><a href="mithril.withAttr.html">m.withAttr</a></li>
<li><a href="mithril.module.html">m.module</a></li>
<li><a href="mithril.trust.html">m.trust</a></li>
<li><a href="mithril.render.html">m.render</a></li>
<li><a href="mithril.redraw.html">m.redraw</a>
<ul>
<li><a href="mithril.redraw.html#strategy">m.redraw.strategy(strategy)</a></li>
</ul>
</li>
</ul>
<h3 id="routing">Routing</h3>
<ul>
<li><a href="mithril.route.html">m.route</a>
<ul>
<li><a href="mithril.route.html#defining-routes">m.route(rootElement, defaultRoute, routes)</a></li>
<li><a href="mithril.route.html#redirecting">m.route(path, params)</a></li>
<li><a href="mithril.route.html#reading-current-route">m.route()</a></li>
<li><a href="mithril.route.html#mode-abstraction">m.route(element)</a></li>
<li><a href="mithril.route.html#mode">m.route.mode</a></li>
<li><a href="mithril.route.html#param">m.route.param</a></li>
</ul>
</li>
</ul>
<h3 id="data">Data</h3>
<ul>
<li><a href="mithril.request.html">m.request</a></li>
<li><a href="mithril.deferred.html">m.deferred</a></li>
<li><a href="mithril.sync.html">m.sync</a></li>
<li><a href="mithril.computation.html">m.startComputation / m.endComputation</a></li>
</ul>
<h2 id="archive">History</h2>
<ul>
<li><a href="roadmap.html">Roadmap</a></li>
<li><a href="change-log.html">Change log</a></li>
</ul>
</div>
<div class="col(9,9,12)">
<h2 id="m-startcomputation-m-endcomputation">m.startComputation / m.endComputation</h2>
<p>Typically, <code>m.startComputation</code> / <code>m.endComputation</code> don't need to be called from application space. These methods are only intended to be used by people who are writing libraries that do things asynchronously.</p>
<p>If you need to do custom asynchronous calls without using Mithril's API, and find that your views are not redrawing, or that you're being forced to call <a href="mithril.redraw.html"><code>m.redraw</code></a> manually, you should consider using <code>m.startComputation</code> / <code>m.endComputation</code> so that Mithril can intelligently auto-redraw once your custom code finishes running.</p>
<p>In order to integrate an asynchronous code to Mithril's autoredrawing system, you should call <code>m.startComputation</code> BEFORE making an asynchronous call, and <code>m.endComputation</code> after the asynchronous callback completes.</p>
<pre><code class="lang-javascript">//this service waits 1 second, logs "hello" and then notifies the view that
//it may start redrawing (if no other asynchronous operations are pending)
var doStuff = function() {
m.startComputation(); //call `startComputation` before the asynchronous `setTimeout`
setTimeout(function() {
console.log("hello");
m.endComputation(); //call `endComputation` at the end of the callback
}, 1000);
};</code></pre>
<p>To integrate synchronous code, call <code>m.startComputation</code> at the beginning of the method, and <code>m.endComputation</code> at the end.</p>
<pre><code class="lang-javascript">window.onfocus = function() {
m.startComputation(); //call before everything else in the event handler
doStuff();
m.endComputation(); //call after everything else in the event handler
}</code></pre>
<p>For each <code>m.startComputation</code> call a library makes, it MUST also make one and ONLY one corresponding <code>m.endComputation</code> call.</p>
<p>You should not use these methods if your code is intended to run repeatedly (e.g. by using <code>setInterval</code>). If you want to repeatedly redraw the view without necessarily waiting for user input, you should manually call <a href="mithril.redraw.html"><code>m.redraw</code></a> within the repeatable context.</p>
<p>Note that failing to call <code>endComputation</code> after a respective <code>startComputation</code> call will halt the redrawing system. It's a good idea to wrap exception-prone code in a <code>try</code> block and call <code>m.endComputation</code> from within the respective <code>finally</code> block, in order to prevent rendering from halting.</p>
<pre><code class="lang-javascript">window.onfocus = function() {
m.startComputation();
try {
doStuff();
}
finally {
m.endComputation(); //redraw regardless of whether `doStuff` threw errors
}
}</code></pre>
<hr>
<h3 id="integrating-multiple-execution-threads">Integrating multiple execution threads</h3>
<p>When <a href="integration.html">integrating with third party libraries</a>, you might find that you need to call asynchronous methods from outside of Mithril's API.</p>
<p>In order to integrate non-trivial asynchronous code to Mithril's auto-redrawing system, you need to ensure all execution threads call <code>m.startComputation</code> / <code>m.endComputation</code>.</p>
<p>An execution thread is basically any amount of code that runs before other asynchronous threads start to run.</p>
<p>Integrating multiple execution threads can be done in a two different ways: in a layered fashion or in comprehensive fashion</p>
<h4 id="layered-integration">Layered integration</h4>
<p>Layered integration is recommended for modular code where many different APIs may be put together at the application level.</p>
<p>Below is an example where various methods implemented with a third party library can be integrated in layered fashion: any of the methods can be used in isolation or in combination.</p>
<p>Notice how <code>doBoth</code> repeatedly calls <code>m.startComputation</code> since that method calls both <code>doSomething</code> and <code>doAnother</code>. This is perfectly valid: there are three asynchronous computations pending after the <code>jQuery.when</code> method is called, and therefore, three pairs of <code>m.startComputation</code> / <code>m.endComputation</code> in play.</p>
<pre><code class="lang-javascript">var doSomething = function(callback) {
m.startComputation(); //call `startComputation` before the asynchronous AJAX request
return jQuery.ajax("/something").done(function() {
if (callback) callback();
m.endComputation(); //call `endComputation` at the end of the callback
});
};
var doAnother = function(callback) {
m.startComputation(); //call `startComputation` before the asynchronous AJAX request
return jQuery.ajax("/another").done(function() {
if (callback) callback();
m.endComputation(); //call `endComputation` at the end of the callback
});
};
var doBoth = function(callback) {
m.startComputation(); //call `startComputation` before the asynchronous synchronization method
jQuery.when(doSomething(), doAnother()).then(function() {
if (callback) callback();
m.endComputation(); //call `endComputation` at the end of the callback
})
};</code></pre>
<h4 id="comprehensive-integration">Comprehensive integration</h4>
<p>Comprehensive integration is recommended if integrating a monolithic series of asynchronous operations. In contrast to layered integration, it minimizes the number of <code>m.startComputation</code> / <code>m.endComputation</code> to avoid clutter.</p>
<p>The example below shows a convoluted series of AJAX requests implemented with a third party library.</p>
<pre><code class="lang-javascript">var doSomething = function(callback) {
m.startComputation(); //call `startComputation` before everything else
jQuery.ajax("/something").done(function() {
doStuff();
jQuery.ajax("/another").done(function() {
doMoreStuff();
jQuery.ajax("/more").done(function() {
if (callback) callback();
m.endComputation(); //call `endComputation` at the end of everything
});
});
});
};</code></pre>
<hr>
<h2 id="integrating-to-legacy-code">Integrating to legacy code</h2>
<p>If you need to add separate widgets to different places on a same page, you can simply initialize each widget as you would a regular Mithril application (i.e. use <code>m.render</code>, <code>m.module</code> or <code>m.route</code>).</p>
<p>There's just one caveat: while simply initializing multiple "islands" in this fashion works, their initialization calls are not aware of each other and can cause redraws too frequently. To optimize rendering, you should add a <code>m.startComputation</code> call before the first widget initialization call, and a <code>m.endComputation</code> after the last widget initialization call in each execution thread.</p>
<pre><code>m.startComputation()
m.module(document.getElementById("widget1-container"), widget1)
m.module(document.getElementById("widget2-container"), widget1)
m.endComputation()</code></pre>
<hr>
<h3 id="signature">Signature</h3>
<p><a href="how-to-read-signatures.html">How to read signatures</a></p>
<pre><code class="lang-clike">void startComputation()</code></pre>
<pre><code class="lang-clike">void endComputation()</code></pre>
</div>
</div>
</div>
</section>
</main>
<footer>
<div class="container">
Released under the <a href="http://opensource.org/licenses/MIT" target="_blank">MIT license</a>
<br />© 2014 Leo Horie
</div>
</footer>
<script src="lib/prism/prism.js"></script>
</body>
</html>