You've already forked The-API-Book
mirror of
https://github.com/twirl/The-API-Book.git
synced 2025-08-10 21:51:42 +02:00
switched to async locks
This commit is contained in:
BIN
docs/API.en.epub
BIN
docs/API.en.epub
Binary file not shown.
@@ -6639,7 +6639,7 @@ api.<span class="hljs-title function_">subscribe</span>(
|
||||
</ul>
|
||||
<p>If you have read the previous chapters thoroughly, the solution to these problems should be obvious. We need to abstract from the fact of loading data and reformulate the issue in high-level terms. We have a shared resource: the space on the screen. Only one offer can be displayed at a time. This means that every actor needing lasting access to the panel must explicitly obtain it. This entails two conclusions:</p>
|
||||
<ul>
|
||||
<li>The access flag must have an explicit name, such as <code>offerFullViewLocked</code>m and not <code>isDataLoading</code>.</li>
|
||||
<li>The access flag must have an explicit name, such as <code>offerFullViewLocked</code>, and not <code>isDataLoading</code>.</li>
|
||||
<li><code>Composer</code> must control this flag, not the offer panel itself (additionally, because preparing data for displaying in the panel is <code>Composer</code>'s responsibility).</li>
|
||||
</ul>
|
||||
<pre><code class="language-typescript"><span class="hljs-keyword">class</span> <span class="hljs-title class_">SearchBoxComposer</span> {
|
||||
@@ -6669,9 +6669,9 @@ api.<span class="hljs-title function_">subscribe</span>(
|
||||
selectOffer (offer) {
|
||||
<span class="hljs-keyword">let</span> lock;
|
||||
<span class="hljs-keyword">try</span> {
|
||||
<span class="hljs-comment">// Trying to catpture the</span>
|
||||
<span class="hljs-comment">// Trying to capture the</span>
|
||||
<span class="hljs-comment">// `offerFullView` resource</span>
|
||||
lock = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
lock = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
<span class="hljs-string">'offerFullView'</span>, <span class="hljs-string">'10s'</span>
|
||||
);
|
||||
<span class="hljs-keyword">let</span> fullData = <span class="hljs-keyword">await</span> api
|
||||
@@ -6696,7 +6696,7 @@ api.<span class="hljs-title function_">subscribe</span>(
|
||||
</code></pre>
|
||||
<p><strong>NB</strong>: the second argument to the <code>acquireLock</code> function is the lock's lifespan (10 seconds, in our case). This implies that the lock will be automatically released after this timeout has passed (which is useful in case we have forgotten to catch an exception or set a timeout for a data load request), thus unblocking the UI.</p>
|
||||
<p>With this approach, we can implement not only locks, but also various scenarios to flexibly manage them. Let's add data regarding the acquirer in the lock function:</p>
|
||||
<pre><code class="language-typescript">lock = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
<pre><code class="language-typescript">lock = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
<span class="hljs-string">'offerFullView'</span>, <span class="hljs-string">'10s'</span>, {
|
||||
<span class="hljs-comment">// Who is trying to acquire a lock</span>
|
||||
<span class="hljs-comment">// and for what reason</span>
|
||||
@@ -6714,12 +6714,12 @@ api.<span class="hljs-title function_">subscribe</span>(
|
||||
<span class="hljs-comment">// of the lock</span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||||
}
|
||||
})
|
||||
});
|
||||
</code></pre>
|
||||
<p>Additionally, we might add a handler to react to losing control — for example, to cancel the request for data if it is no longer needed:</p>
|
||||
<pre><code class="language-typescript">lock.<span class="hljs-property">events</span>.<span class="hljs-title function_">on</span>(<span class="hljs-string">'lost'</span>, <span class="hljs-function">() =></span> {
|
||||
<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">cancelFullOfferDataLoad</span>();
|
||||
})
|
||||
});
|
||||
</code></pre>
|
||||
<p>The shared resource access control partner aligns well with the “model” pattern: actors can acquire read and/or write locks for specific data fields (or groups of fields) of the model.</p>
|
||||
<p><strong>NB</strong>: we could have addressed the data load problem differently:</p>
|
||||
|
BIN
docs/API.en.pdf
BIN
docs/API.en.pdf
Binary file not shown.
BIN
docs/API.ru.epub
BIN
docs/API.ru.epub
Binary file not shown.
@@ -6699,7 +6699,7 @@ api.<span class="hljs-title function_">subscribe</span>(
|
||||
<span class="hljs-keyword">try</span> {
|
||||
<span class="hljs-comment">// Пытаемся захватить ресурс</span>
|
||||
<span class="hljs-comment">// `offerFullView`</span>
|
||||
lock = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
lock = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
<span class="hljs-string">'offerFullView'</span>, <span class="hljs-string">'10s'</span>
|
||||
);
|
||||
<span class="hljs-keyword">let</span> fullData = <span class="hljs-keyword">await</span> api
|
||||
@@ -6724,7 +6724,7 @@ api.<span class="hljs-title function_">subscribe</span>(
|
||||
</code></pre>
|
||||
<p><strong>NB</strong>: вторым параметром в <code>acquireLock</code> мы передали максимальное время жизни блокировки — 10 секунд. Если в течение этого времени блокировка не снята (например, в случае, если мы забыли обработать какое-то исключение или выставить таймаут на запрос к серверу), она будет отменена автоматически, и интерфейс будет разблокирован.</p>
|
||||
<p>В таком подходе мы можем реализовать не только блокировки, но и различные сценарии, которые позволяют нам более гибко ими управлять. Добавим в функцию захвата ресурса дополнительные данные о целях захвата:</p>
|
||||
<pre><code class="language-typescript">lock = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
<pre><code class="language-typescript">lock = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">acquireLock</span>(
|
||||
<span class="hljs-string">'offerFullView'</span>, <span class="hljs-string">'10s'</span>, {
|
||||
<span class="hljs-comment">// Добавляем описание,</span>
|
||||
<span class="hljs-comment">// кто и зачем пытается</span>
|
||||
@@ -6742,12 +6742,12 @@ api.<span class="hljs-title function_">subscribe</span>(
|
||||
<span class="hljs-comment">// Иначе запрещаем перехват</span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||||
}
|
||||
})
|
||||
});
|
||||
</code></pre>
|
||||
<p>Дополнительно мы можем ввести и обработку потери контроля ресурса — например, отменить загрузку данных, которые больше не нужны.</p>
|
||||
<pre><code class="language-typescript">lock.<span class="hljs-property">events</span>.<span class="hljs-title function_">on</span>(<span class="hljs-string">'lost'</span>, <span class="hljs-function">() =></span> {
|
||||
<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">cancelFullOfferDataLoad</span>();
|
||||
})
|
||||
});
|
||||
</code></pre>
|
||||
<p>Паттерн контроля разделяемых ресурсов также хорошо сочетается с паттерном «модель»: акторы могут захватывать доступ на чтение и/или изменение свойств или групп свойств модели.</p>
|
||||
<p><strong>NB</strong>: мы могли бы решить проблему подгрузки данных иначе:</p>
|
||||
|
BIN
docs/API.ru.pdf
BIN
docs/API.ru.pdf
Binary file not shown.
@@ -97,9 +97,9 @@ class SearchBoxComposer {
|
||||
selectOffer (offer) {
|
||||
let lock;
|
||||
try {
|
||||
// Trying to catpture the
|
||||
// Trying to capture the
|
||||
// `offerFullView` resource
|
||||
lock = this.acquireLock(
|
||||
lock = await this.acquireLock(
|
||||
'offerFullView', '10s'
|
||||
);
|
||||
let fullData = await api
|
||||
@@ -128,7 +128,7 @@ class SearchBoxComposer {
|
||||
With this approach, we can implement not only locks, but also various scenarios to flexibly manage them. Let's add data regarding the acquirer in the lock function:
|
||||
|
||||
```typescript
|
||||
lock = this.acquireLock(
|
||||
lock = await this.acquireLock(
|
||||
'offerFullView', '10s', {
|
||||
// Who is trying to acquire a lock
|
||||
// and for what reason
|
||||
|
@@ -99,7 +99,7 @@ class SearchBoxComposer {
|
||||
try {
|
||||
// Пытаемся захватить ресурс
|
||||
// `offerFullView`
|
||||
lock = this.acquireLock(
|
||||
lock = await this.acquireLock(
|
||||
'offerFullView', '10s'
|
||||
);
|
||||
let fullData = await api
|
||||
@@ -128,7 +128,7 @@ class SearchBoxComposer {
|
||||
В таком подходе мы можем реализовать не только блокировки, но и различные сценарии, которые позволяют нам более гибко ими управлять. Добавим в функцию захвата ресурса дополнительные данные о целях захвата:
|
||||
|
||||
```typescript
|
||||
lock = this.acquireLock(
|
||||
lock = await this.acquireLock(
|
||||
'offerFullView', '10s', {
|
||||
// Добавляем описание,
|
||||
// кто и зачем пытается
|
||||
|
Reference in New Issue
Block a user