patron-oop 1.45.0 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/patron.cjs +106 -35
- package/dist/patron.cjs.map +1 -1
- package/dist/patron.d.ts +40 -1
- package/dist/patron.js +103 -36
- package/dist/patron.js.map +1 -1
- package/dist/patron.min.js +1 -1
- package/dist/patron.min.mjs +1 -1
- package/dist/patron.min.mjs.map +1 -1
- package/dist/patron.mjs +103 -36
- package/dist/patron.mjs.map +1 -1
- package/docs/README.md +3 -0
- package/docs/assets/css/base.css +42 -0
- package/docs/assets/favicon/android-icon-144x144.png +0 -0
- package/docs/assets/favicon/android-icon-192x192.png +0 -0
- package/docs/assets/favicon/android-icon-36x36.png +0 -0
- package/docs/assets/favicon/android-icon-48x48.png +0 -0
- package/docs/assets/favicon/android-icon-72x72.png +0 -0
- package/docs/assets/favicon/android-icon-96x96.png +0 -0
- package/docs/assets/favicon/apple-icon-114x114.png +0 -0
- package/docs/assets/favicon/apple-icon-120x120.png +0 -0
- package/docs/assets/favicon/apple-icon-144x144.png +0 -0
- package/docs/assets/favicon/apple-icon-152x152.png +0 -0
- package/docs/assets/favicon/apple-icon-180x180.png +0 -0
- package/docs/assets/favicon/apple-icon-57x57.png +0 -0
- package/docs/assets/favicon/apple-icon-60x60.png +0 -0
- package/docs/assets/favicon/apple-icon-72x72.png +0 -0
- package/docs/assets/favicon/apple-icon-76x76.png +0 -0
- package/docs/assets/favicon/apple-icon-precomposed.png +0 -0
- package/docs/assets/favicon/apple-icon.png +0 -0
- package/docs/assets/favicon/browserconfig.xml +2 -0
- package/docs/assets/favicon/favicon-16x16.png +0 -0
- package/docs/assets/favicon/favicon-32x32.png +0 -0
- package/docs/assets/favicon/favicon-96x96.png +0 -0
- package/docs/assets/favicon/favicon.ico +0 -0
- package/docs/assets/favicon/manifest.json +41 -0
- package/docs/assets/favicon/ms-icon-144x144.png +0 -0
- package/docs/assets/favicon/ms-icon-150x150.png +0 -0
- package/docs/assets/favicon/ms-icon-310x310.png +0 -0
- package/docs/assets/favicon/ms-icon-70x70.png +0 -0
- package/docs/assets/img/404.jpg +0 -0
- package/docs/assets/img/angular_16.jpg +0 -0
- package/docs/assets/img/angular_32.jpg +0 -0
- package/docs/assets/img/eo_16.jpg +0 -0
- package/docs/assets/img/eo_big.png +0 -0
- package/docs/assets/img/github_16.jpg +0 -0
- package/docs/assets/img/logo.jpg +0 -0
- package/docs/assets/img/philosofy/observable.jpg +0 -0
- package/docs/assets/img/philosofy/responsible.jpg +0 -0
- package/docs/assets/img/philosofy/result.jpg +0 -0
- package/docs/assets/img/philosofy/tell.jpg +0 -0
- package/docs/assets/img/react_16.jpg +0 -0
- package/docs/assets/img/react_32.jpg +0 -0
- package/docs/assets/img/vue_16.jpg +0 -0
- package/docs/assets/img/vue_32.jpg +0 -0
- package/docs/assets/js/components/linkDynamic.mjs +11 -0
- package/docs/assets/js/components/linkReloadable.mjs +13 -0
- package/docs/assets/js/entrypoints/compatibility.mjs +31 -0
- package/docs/assets/js/entrypoints/components.mjs +2 -0
- package/docs/assets/js/entrypoints/examples.mjs +25 -0
- package/docs/assets/js/entrypoints/factory.mjs +20 -0
- package/docs/assets/js/entrypoints/guest.mjs +61 -0
- package/docs/assets/js/entrypoints/index.mjs +110 -0
- package/docs/assets/js/entrypoints/integrations.mjs +36 -0
- package/docs/assets/js/entrypoints/patron.mjs +46 -0
- package/docs/assets/js/entrypoints/source.mjs +76 -0
- package/docs/assets/js/entrypoints/terminology.mjs +51 -0
- package/docs/assets/js/entrypoints/utils.mjs +61 -0
- package/docs/assets/js/lib/StyleFetched.mjs +14 -0
- package/docs/assets/js/routing.mjs +110 -0
- package/docs/assets/schemes/dip.html +28 -0
- package/docs/favicon.ico +0 -0
- package/docs/index-dev.html +346 -0
- package/docs/index.html +346 -0
- package/docs/manifest.json +41 -0
- package/docs/pages/404.html +9 -0
- package/docs/pages/common/layout.html +17 -0
- package/docs/pages/compatibility/dip.html +82 -0
- package/docs/pages/compatibility/elegant-objects.html +373 -0
- package/docs/pages/compatibility/layout.html +17 -0
- package/docs/pages/examples/errors.html +167 -0
- package/docs/pages/examples/index.html +10 -0
- package/docs/pages/examples.html +41 -0
- package/docs/pages/factory/index.html +18 -0
- package/docs/pages/factory.html +36 -0
- package/docs/pages/guest/guest-applied.html +51 -0
- package/docs/pages/guest/guest-cast.html +219 -0
- package/docs/pages/guest/guest-disposable.html +147 -0
- package/docs/pages/guest/guest-executor-applied.html +65 -0
- package/docs/pages/guest/guest-object.html +101 -0
- package/docs/pages/guest/guest-pool.html +107 -0
- package/docs/pages/guest/guest-sync.html +66 -0
- package/docs/pages/guest/index.html +115 -0
- package/docs/pages/guest.html +59 -0
- package/docs/pages/index.html +72 -0
- package/docs/pages/integrations/angular.html +5 -0
- package/docs/pages/integrations/layout.html +17 -0
- package/docs/pages/integrations/react.html +7 -0
- package/docs/pages/integrations/vue.html +102 -0
- package/docs/pages/patron/index.html +140 -0
- package/docs/pages/patron/patron-applied.html +66 -0
- package/docs/pages/patron/patron-executor-applied.html +94 -0
- package/docs/pages/patron/patron-once.html +110 -0
- package/docs/pages/patron/patron-pool.html +99 -0
- package/docs/pages/patron.html +50 -0
- package/docs/pages/philosofy.html +210 -0
- package/docs/pages/source/index.html +167 -0
- package/docs/pages/source/source-active.html +113 -0
- package/docs/pages/source/source-all.html +129 -0
- package/docs/pages/source/source-applied.html +73 -0
- package/docs/pages/source/source-dynamic.html +93 -0
- package/docs/pages/source/source-executor-applied.html +64 -0
- package/docs/pages/source/source-map.html +192 -0
- package/docs/pages/source/source-once.html +73 -0
- package/docs/pages/source/source-race.html +171 -0
- package/docs/pages/source/source-sequence.html +160 -0
- package/docs/pages/source/source-with-pool.html +102 -0
- package/docs/pages/source/source.html +167 -0
- package/docs/pages/source.html +68 -0
- package/docs/pages/terminology/guest.html +14 -0
- package/docs/pages/terminology/index.html +6 -0
- package/docs/pages/terminology/introduction.html +25 -0
- package/docs/pages/terminology/patron.html +10 -0
- package/docs/pages/terminology/source.html +55 -0
- package/docs/pages/terminology/visitor.html +19 -0
- package/docs/pages/terminology.html +53 -0
- package/docs/pages/utils/give.html +47 -0
- package/docs/pages/utils/index.html +24 -0
- package/docs/pages/utils/is-guest-aware.html +22 -0
- package/docs/pages/utils/is-guest.html +21 -0
- package/docs/pages/utils/is-patron-in-pools.html +53 -0
- package/docs/pages/utils/private.html +44 -0
- package/docs/pages/utils/remove-patron-from-pools.html +57 -0
- package/docs/pages/utils/value.html +47 -0
- package/docs/pages/utils.html +61 -0
- package/eslint.config.mjs +6 -0
- package/package.json +1 -1
- package/src/Patron/PatronApplied.ts +22 -0
- package/src/Patron/PatronExecutorApplied.ts +25 -0
- package/src/index.ts +4 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
<h1 class="pb-3 text-xl font-semibold text-gray-600">Класс PatronPool</h1>
|
2
|
+
|
3
|
+
<a
|
4
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Patron/PatronPool.ts"
|
5
|
+
target="_blank"
|
6
|
+
class="inline-flex gap-1 items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0 mb-4"
|
7
|
+
>
|
8
|
+
<img
|
9
|
+
src="./assets/img/github_16.jpg"
|
10
|
+
width="16"
|
11
|
+
height="16"
|
12
|
+
/>
|
13
|
+
PatronPool на GitHub
|
14
|
+
</a>
|
15
|
+
|
16
|
+
<p class="text-gray-600 text-lg mb-4">
|
17
|
+
Предназначен для хранения списка
|
18
|
+
<span class="dynamic-navigation">
|
19
|
+
<a
|
20
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
21
|
+
href="/terminology/the-patron"
|
22
|
+
>
|
23
|
+
патронов
|
24
|
+
</a>
|
25
|
+
</span>
|
26
|
+
, которым нужно передавать значения
|
27
|
+
</p>
|
28
|
+
|
29
|
+
<p class="text-gray-600 text-lg mb-4">
|
30
|
+
Полезно для организации списка подписчиков на обновление данных какого-то
|
31
|
+
<span class="dynamic-navigation">
|
32
|
+
<a
|
33
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
34
|
+
href="/terminology/the-source"
|
35
|
+
>
|
36
|
+
источника
|
37
|
+
</a>
|
38
|
+
</span>
|
39
|
+
. Сам по себе класс PatronPool - достаточно низкоуровневый и желательно
|
40
|
+
использовать класс Source, который именно является источником значений (у
|
41
|
+
Source под капотом работает PatornPool)
|
42
|
+
</p>
|
43
|
+
|
44
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Пример 1.</p>
|
45
|
+
<pre class="mb-4"><code class="language-js">import {
|
46
|
+
PatronPool,
|
47
|
+
Patron
|
48
|
+
} from 'patron-oop';
|
49
|
+
|
50
|
+
const pool = new PatronPool();
|
51
|
+
|
52
|
+
pool.add(new Patron((value) => {
|
53
|
+
document.querySelector('.patron-pool-result1').textContent = value + ' 1';
|
54
|
+
}));
|
55
|
+
pool.add(new Patron((value) => {
|
56
|
+
document.querySelector('.patron-pool-result2').textContent = value + ' 2';
|
57
|
+
}));
|
58
|
+
|
59
|
+
pool.give('Значение из пула');
|
60
|
+
</code></pre>
|
61
|
+
|
62
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Результат 1.</p>
|
63
|
+
<div class="example mb-4">
|
64
|
+
<div class="patron-pool-result1">Нет результата 1!</div>
|
65
|
+
<div class="patron-pool-result2">Нет результата 2!</div>
|
66
|
+
</div>
|
67
|
+
<script type="module">
|
68
|
+
import { PatronPool, Patron } from "patron-oop";
|
69
|
+
|
70
|
+
const pool = new PatronPool();
|
71
|
+
|
72
|
+
pool.add(
|
73
|
+
new Patron((value) => {
|
74
|
+
document.querySelector(".patron-pool-result1").textContent = value + " 1";
|
75
|
+
})
|
76
|
+
);
|
77
|
+
pool.add(
|
78
|
+
new Patron((value) => {
|
79
|
+
document.querySelector(".patron-pool-result2").textContent = value + " 2";
|
80
|
+
})
|
81
|
+
);
|
82
|
+
|
83
|
+
pool.give("Значение из пула");
|
84
|
+
</script>
|
85
|
+
|
86
|
+
<div class="font-bold mt-8">Смотрите также</div>
|
87
|
+
|
88
|
+
<p class="text-gray-600 text-lg mb-4 dynamic-navigation">
|
89
|
+
<a
|
90
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
91
|
+
href="/source"
|
92
|
+
>Source</a
|
93
|
+
>
|
94
|
+
<a
|
95
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
96
|
+
href="/patron"
|
97
|
+
>Patron</a
|
98
|
+
>
|
99
|
+
</p>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<section class="text-gray-600 body-font">
|
2
|
+
<div class="py-1 mx-auto flex flex-col w-full">
|
3
|
+
<div class="lg:w-4/6 mx-auto w-full">
|
4
|
+
<div class="flex flex-col sm:flex-row w-full">
|
5
|
+
<div class="sm:w-1/3 text-center">
|
6
|
+
<div
|
7
|
+
class="flex flex-col items-center text-center justify-center patron-menu"
|
8
|
+
>
|
9
|
+
<h2 class="font-medium title-font text-gray-900 text-lg">
|
10
|
+
<a href="/patron"> Patron </a>
|
11
|
+
</h2>
|
12
|
+
<div class="w-12 h-1 bg-indigo-500 rounded mt-2 mb-4"></div>
|
13
|
+
<ul class="text-gray-900">
|
14
|
+
<li class="w-full border-b-2 border-neutral-100 py-4">
|
15
|
+
<a href="/patron/patron-once"> PatronOnce </a>
|
16
|
+
</li>
|
17
|
+
<li class="w-full border-b-2 border-neutral-100 py-4">
|
18
|
+
<a href="/patron/patron-pool"> PatronPool </a>
|
19
|
+
</li>
|
20
|
+
<li class="w-full border-b-2 border-neutral-100 py-4">
|
21
|
+
<a href="/patron/patron-applied"> PatronApplied </a>
|
22
|
+
</li>
|
23
|
+
<li class="w-full border-b-2 border-neutral-100 py-4">
|
24
|
+
<a href="/patron/patron-executor-applied"> PatronExecutorApplied </a>
|
25
|
+
</li>
|
26
|
+
</ul>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
<div
|
30
|
+
class="sm:w-2/3 sm:pl-8 sm:border-l border-gray-200 sm:border-t-0 border-t mt-4 sm:mt-0"
|
31
|
+
>
|
32
|
+
<div class="patron-loader">
|
33
|
+
<div class="w-full flex justify-center">
|
34
|
+
<div
|
35
|
+
class="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-e-transparent align-[-0.125em] text-indigo-500 motion-reduce:animate-[spin_1.5s_linear_infinite]"
|
36
|
+
role="status"
|
37
|
+
>
|
38
|
+
<span
|
39
|
+
class="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]"
|
40
|
+
>Loading...</span
|
41
|
+
>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
<div class="patron-page-area"></div>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
</section>
|
@@ -0,0 +1,210 @@
|
|
1
|
+
<section class="text-gray-600 body-font">
|
2
|
+
<div class="mx-auto flex py-1 items-center justify-center flex-col">
|
3
|
+
<div class="lg:w-2/3 w-full">
|
4
|
+
<h1 class="pb-3 text-xl font-semibold text-gray-600">
|
5
|
+
Tell don't ask + trust
|
6
|
+
</h1>
|
7
|
+
<img
|
8
|
+
class="float-left m-3 my-0"
|
9
|
+
src="./assets/img/philosofy/tell.jpg"
|
10
|
+
width="150"
|
11
|
+
height="200"
|
12
|
+
/>
|
13
|
+
<p class="text-gray-600 text-lg mb-4">
|
14
|
+
Идея проекта зародилась из принципа
|
15
|
+
<a
|
16
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
17
|
+
href="https://toolshed.com/articles/1998-07-01-TellDontAsk.html"
|
18
|
+
target="_blank"
|
19
|
+
>Tell don't ask</a
|
20
|
+
>. Оригинальная версия принципа говорит о том, что мы не должны
|
21
|
+
принимать решение какой метод объекта вызывать на основе данных от этого
|
22
|
+
объекта, а должны просто сказать объекту, что он должен сделать
|
23
|
+
</p>
|
24
|
+
<p class="text-gray-600 text-lg mb-4">
|
25
|
+
Этот принцип натолкнул на размышления о том, как на самом деле объекты в
|
26
|
+
программе общаются друг с другом. Когда объект А вызывает метод объекта
|
27
|
+
B и ожидает результат, который будет возвращен методом объекта B через
|
28
|
+
return, такая организация кода заставляет объект B отвечать даже в те
|
29
|
+
моменты, когда у объекта B нет какого-то хорошего, значащего результата
|
30
|
+
</p>
|
31
|
+
<p class="text-gray-600 text-lg mb-4">
|
32
|
+
Такая ситуация при использовании return заставляет объекты подобные B
|
33
|
+
возвращать не полные результаты или вообще не возвращать результаты.
|
34
|
+
Например, если объект B работает асинхронно, обращаясь к серверу, то
|
35
|
+
объект B не может вернуть значение в условиях JS. Объект B может вернуть
|
36
|
+
только Promise - обещание того что значение будет когда-то позже, но
|
37
|
+
проблема в том, что сам объект B больше не отвечает за этот результат,
|
38
|
+
результат может вернуться, а может и не вернуться, даже если мы
|
39
|
+
обработаем ошибку с помощью catch мы все равно обязаны что-то отвечать
|
40
|
+
ожидающему объекту, что - то не значащее, что нужно будет перепроверять,
|
41
|
+
а следовательно доверие к объекту B пропадет, каждый его ответ нужно
|
42
|
+
проверять
|
43
|
+
</p>
|
44
|
+
<p class="text-gray-600 text-lg mb-4">
|
45
|
+
Также возможна ситуация, что у объекта B просто нет ответа и нам
|
46
|
+
приходится возвращать null, а null переносит ответственность на объект
|
47
|
+
который общается с объектом B. И получается что с объектом B уже
|
48
|
+
общаться не приятно, потому что он не может гарантировать результат, его
|
49
|
+
все время нужно перепроверять, никто ему не доверяет
|
50
|
+
</p>
|
51
|
+
<div class="clear-both"></div>
|
52
|
+
<h2 class="pb-3 text-xl font-semibold text-gray-600">Responsible</h2>
|
53
|
+
<img
|
54
|
+
class="float-left m-3 my-0"
|
55
|
+
src="./assets/img/philosofy/responsible.jpg"
|
56
|
+
width="150"
|
57
|
+
height="200"
|
58
|
+
/>
|
59
|
+
<p class="text-gray-600 text-lg mb-4">
|
60
|
+
Всё что описано выше под заголовком <b>Tell don't ask</b> говорит нам о
|
61
|
+
том, что хороший объект должен уметь отвечать за те результаты, которые
|
62
|
+
другие объекты ожидают от него получить. И чтобы реализация этой
|
63
|
+
ответственности за результат стала возможной - объект у которого
|
64
|
+
результат есть должен видеть того, кому этот результат нужен, чтобы
|
65
|
+
полностью контролировать отдачу результата своему
|
66
|
+
<span class="dynamic-navigation">
|
67
|
+
<a
|
68
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
69
|
+
href="/terminology/visitor"
|
70
|
+
>
|
71
|
+
посетителю
|
72
|
+
</a>
|
73
|
+
</span>
|
74
|
+
Вокруг этой ключевой идеи и построена вся библиотека. Посетители объекта
|
75
|
+
делятся на
|
76
|
+
<span class="dynamic-navigation">
|
77
|
+
<a
|
78
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
79
|
+
href="/terminology/the-guest"
|
80
|
+
>
|
81
|
+
гостей
|
82
|
+
</a>
|
83
|
+
</span>
|
84
|
+
- те кому сообщить значение нужно один раз и забыть о нем пока он сам не
|
85
|
+
вернется если захочет и
|
86
|
+
|
87
|
+
<span class="dynamic-navigation">
|
88
|
+
<a
|
89
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
90
|
+
href="/terminology/the-patron"
|
91
|
+
>
|
92
|
+
патроны
|
93
|
+
</a>
|
94
|
+
</span>
|
95
|
+
- те кому нужно постоянно сообщать о новых значениях, пока они сами не
|
96
|
+
решат удалиться из
|
97
|
+
<span class="dynamic-navigation">
|
98
|
+
<a
|
99
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
100
|
+
href="/patron/patron-pool"
|
101
|
+
>
|
102
|
+
пула патронов
|
103
|
+
</a>
|
104
|
+
</span>
|
105
|
+
</p>
|
106
|
+
<div class="clear-both"></div>
|
107
|
+
<h2 class="pb-3 text-xl font-semibold text-gray-600">Result</h2>
|
108
|
+
<img
|
109
|
+
class="float-left m-3 my-0"
|
110
|
+
src="./assets/img/philosofy/result.jpg"
|
111
|
+
width="150"
|
112
|
+
height="200"
|
113
|
+
/>
|
114
|
+
<p class="text-gray-600 text-lg mb-4">
|
115
|
+
Из того что написано под заголовком <b>Responsible</b> можно сделать
|
116
|
+
вывод что использование Библиотеки Patron накладывает на вас ограничение
|
117
|
+
- не использовать return, а вместо этого возвращать данные посетителю
|
118
|
+
вызывая его метод give, либо пользуясь отдельной функцией
|
119
|
+
<span class="dynamic-navigation">
|
120
|
+
<a
|
121
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
122
|
+
href="/utils/give"
|
123
|
+
>
|
124
|
+
give
|
125
|
+
</a>
|
126
|
+
</span>
|
127
|
+
</p>
|
128
|
+
<p class="text-gray-600 text-lg mb-4">
|
129
|
+
Но в этом разделе(Result) хотелось бы отметить еще одну важную
|
130
|
+
философскую основу, на которую идет опора при разработке на библиотеке
|
131
|
+
Patron. Классы(статический код class) которые мы создаем считаются
|
132
|
+
результатом который нам нужен по нашей логике, позже при создании
|
133
|
+
объекта из класса мы получаем частично примененную версию класса тот же
|
134
|
+
класс с привязанными данными к нему и позже, чтобы получить конкретный
|
135
|
+
результат вычисления в виде данных нам нужно вызвать метод объекта.
|
136
|
+
Последовательность описанная в предыдущем предложении противоположна
|
137
|
+
процедурной последовательности выполнения - сначала вычисление потом
|
138
|
+
результат. Программируя в ООП стиле мы имеем результаты раньше чем
|
139
|
+
происходит вычисление. Наши классы и есть представления нужных нам
|
140
|
+
результатов. Эта идея считается ключевой для понимания принципа
|
141
|
+
разработки последующего кода. Мы создаем большой результат, потом
|
142
|
+
создаем результаты поменьше нужные большому, и так далее пока не опишем
|
143
|
+
наше приложение. Пирамида результатов строится сверху вниз от самого
|
144
|
+
важного для нашей бизнес логики к менее важному и более конкретному
|
145
|
+
(конкретность тут в смысле относящийся к вычислению на компьютере)
|
146
|
+
</p>
|
147
|
+
<div class="clear-both"></div>
|
148
|
+
<h2 class="pb-3 text-xl font-semibold text-gray-600">
|
149
|
+
Посетитель + Наблюдатель
|
150
|
+
</h2>
|
151
|
+
<img
|
152
|
+
class="float-left m-3 my-0"
|
153
|
+
src="./assets/img/philosofy/observable.jpg"
|
154
|
+
width="150"
|
155
|
+
height="200"
|
156
|
+
/>
|
157
|
+
<p class="text-gray-600 text-lg mb-4">
|
158
|
+
Можно сказать, что библиотека Patron построена на основе(или
|
159
|
+
вдохновлена) двух паттернов(или двумя паттернами) ООП: Наблюдатель и
|
160
|
+
Посетитель. Объекты имеющие данные не отдают их неизвестно кому
|
161
|
+
(оператором return), а вместо этого ждут посетителя и отдают данные
|
162
|
+
вежливому посетителю который пришел и
|
163
|
+
<span class="dynamic-navigation">
|
164
|
+
<a
|
165
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
166
|
+
href="/terminology/introduction"
|
167
|
+
>
|
168
|
+
представился
|
169
|
+
</a>
|
170
|
+
</span>
|
171
|
+
Посетитель может представиться патроном, что для объекта источника
|
172
|
+
данных будет значить что в случае если у этого объекта будут новые
|
173
|
+
данные, то патрону будет интересно об этих данных узнать. Общение между
|
174
|
+
объектами происходит уважительно, никто никого не использует и не
|
175
|
+
принуждает давать ответы. Если источнику данных нечего сказать, то он
|
176
|
+
может просто молчать и не давать бесполезные ответы
|
177
|
+
</p>
|
178
|
+
<div class="clear-both"></div>
|
179
|
+
<h2 class="pb-3 text-xl font-semibold text-gray-600">
|
180
|
+
Потребители и Источники
|
181
|
+
</h2>
|
182
|
+
<p class="text-gray-600 text-lg mb-4">
|
183
|
+
Библиотека выделяет две основные категории классов. Первая - потребители
|
184
|
+
это классы или функции совместимые с интерфейсом
|
185
|
+
<a
|
186
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
187
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Guest/Guest.ts#L17"
|
188
|
+
>
|
189
|
+
GuestType
|
190
|
+
</a>
|
191
|
+
, этой категории нужны данные. Вторая источники - эта категория имеет
|
192
|
+
данные и может отдать их потребителю, источники совместимы с интерфейсом
|
193
|
+
<a
|
194
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
195
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Source/Source.ts#L3-L5"
|
196
|
+
>
|
197
|
+
SourceType
|
198
|
+
</a>
|
199
|
+
</p>
|
200
|
+
<p class="text-gray-600 text-lg mb-4">
|
201
|
+
Хороший пример разделения на потребители и источники это классы для
|
202
|
+
описания <b>REST</b>, например запросы с методом <b>GET</b> это
|
203
|
+
источники данных, потому что могут отдать данные после получения ответа
|
204
|
+
от сервера, а запросы с методами <b>PUT</b>, <b>POST</b>,
|
205
|
+
<b>DELETE</b> это потребители, потому что могут совершить действие после
|
206
|
+
получения данных.
|
207
|
+
</p>
|
208
|
+
</div>
|
209
|
+
</div>
|
210
|
+
</section>
|
@@ -0,0 +1,167 @@
|
|
1
|
+
<h1 class="pb-3 text-xl font-semibold text-gray-600">Класс Source</h1>
|
2
|
+
|
3
|
+
<a
|
4
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Source/Source.ts"
|
5
|
+
target="_blank"
|
6
|
+
class="inline-flex gap-1 items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0 mb-4"
|
7
|
+
>
|
8
|
+
<img
|
9
|
+
src="./assets/img/github_16.jpg"
|
10
|
+
width="16"
|
11
|
+
height="16"
|
12
|
+
/>
|
13
|
+
Source на GitHub
|
14
|
+
</a>
|
15
|
+
|
16
|
+
<p class="text-gray-600 text-lg mb-4">
|
17
|
+
Предназначен для создания объектов, которые будут
|
18
|
+
<span class="dynamic-navigation">
|
19
|
+
<a
|
20
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
21
|
+
href="/terminology/the-source"
|
22
|
+
>
|
23
|
+
источниками данных
|
24
|
+
</a>
|
25
|
+
</span>
|
26
|
+
, логика этих объектов основана на переданной функции-колбэке
|
27
|
+
</p>
|
28
|
+
|
29
|
+
<p class="text-gray-600 text-lg mb-4">
|
30
|
+
Полезно в случаях, когда нужно создать новый объект с уникальным поведением по
|
31
|
+
генерации данных без создания для этого отдельного класса
|
32
|
+
</p>
|
33
|
+
|
34
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Пример 1.</p>
|
35
|
+
<pre class="mb-4"><code class="language-js">import {
|
36
|
+
Source,
|
37
|
+
give
|
38
|
+
} from 'patron-oop';
|
39
|
+
|
40
|
+
const timestamp = new Source((guest) => {
|
41
|
+
give(Date.now(), guest);
|
42
|
+
});
|
43
|
+
timestamp.value((timestamp) => {
|
44
|
+
console.log('timestamp is', timestamp);
|
45
|
+
});
|
46
|
+
</code></pre>
|
47
|
+
|
48
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Результат 1.</p>
|
49
|
+
<div class="example mb-4">
|
50
|
+
<span class="guest-result">Result here</span>
|
51
|
+
</div>
|
52
|
+
<script type="module">
|
53
|
+
import { Source, give } from "patron-oop";
|
54
|
+
|
55
|
+
const timestamp = new Source((guest) => {
|
56
|
+
give(Date.now(), guest);
|
57
|
+
});
|
58
|
+
timestamp.value((timestamp) => {
|
59
|
+
document.querySelector(
|
60
|
+
".guest-result"
|
61
|
+
).textContent = `timestamp is ${timestamp}`;
|
62
|
+
});
|
63
|
+
</script>
|
64
|
+
|
65
|
+
<p class="text-gray-600 text-lg mb-4">
|
66
|
+
Источником данных может быть не только объект, но и функция вида
|
67
|
+
<em>(guest) => guest('value')</em>. Напрямую можно обратиться к такому
|
68
|
+
источнику через функцию
|
69
|
+
<link-reloadable
|
70
|
+
target-blank
|
71
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Source/Source.ts#L11"
|
72
|
+
>
|
73
|
+
value
|
74
|
+
</link-reloadable>
|
75
|
+
</p>
|
76
|
+
|
77
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Пример 2.</p>
|
78
|
+
<pre class="mb-4"><code class="language-js">import {
|
79
|
+
give,
|
80
|
+
value
|
81
|
+
} from "patron-oop";
|
82
|
+
|
83
|
+
const helloSource = (guest) => {
|
84
|
+
setTimeout(() => {
|
85
|
+
give("Hello world", guest);
|
86
|
+
}, 1000);
|
87
|
+
};
|
88
|
+
|
89
|
+
value(helloSource, (greeting) => {
|
90
|
+
document.querySelector(
|
91
|
+
".guest-result-2"
|
92
|
+
).textContent = `greeting is "${greeting}"`;
|
93
|
+
});
|
94
|
+
</code></pre>
|
95
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Результат 2.</p>
|
96
|
+
<div class="example mb-4">
|
97
|
+
<span class="guest-result-2">Result here</span>
|
98
|
+
</div>
|
99
|
+
<script type="module">
|
100
|
+
import { give, value } from "patron-oop";
|
101
|
+
|
102
|
+
const helloSource = (guest) => {
|
103
|
+
setTimeout(() => {
|
104
|
+
give("Hello world", guest);
|
105
|
+
}, 1000);
|
106
|
+
};
|
107
|
+
|
108
|
+
value(helloSource, (greeting) => {
|
109
|
+
document.querySelector(
|
110
|
+
".guest-result-2"
|
111
|
+
).textContent = `greeting is "${greeting}"`;
|
112
|
+
});
|
113
|
+
</script>
|
114
|
+
|
115
|
+
<p class="text-gray-600 text-lg mb-4">
|
116
|
+
Или можно передать источник-функцию в виде зависимости объектам, которые
|
117
|
+
ожидают интерфейс SourceType, в примере ниже используется комбинация
|
118
|
+
<link-dynamic href="/source/source-all">SourceAll</link-dynamic>
|
119
|
+
и источников-фукнций
|
120
|
+
</p>
|
121
|
+
|
122
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Пример 3.</p>
|
123
|
+
<pre class="mb-4"><code class="language-js">import {
|
124
|
+
SourceAll,
|
125
|
+
give,
|
126
|
+
value
|
127
|
+
} from "patron-oop";
|
128
|
+
|
129
|
+
const all = new SourceAll();
|
130
|
+
value(give.bind(null, 1), all.guestKey("one"));
|
131
|
+
value(give.bind(null, 2), all.guestKey("two"));
|
132
|
+
|
133
|
+
all.value(({ one, two }) => {
|
134
|
+
document.querySelector(".guest-result-3").textContent = `one + two = "${
|
135
|
+
one + two
|
136
|
+
}"`;
|
137
|
+
});
|
138
|
+
</code></pre>
|
139
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Результат 3.</p>
|
140
|
+
<div class="example mb-4">
|
141
|
+
<span class="guest-result-3">Result here</span>
|
142
|
+
</div>
|
143
|
+
<script type="module">
|
144
|
+
import { SourceAll, give, value } from "patron-oop";
|
145
|
+
|
146
|
+
const all = new SourceAll();
|
147
|
+
value(give.bind(null, 1), all.guestKey("one"));
|
148
|
+
value(give.bind(null, 2), all.guestKey("two"));
|
149
|
+
|
150
|
+
all.value(({ one, two }) => {
|
151
|
+
document.querySelector(".guest-result-3").textContent = `one + two = "${
|
152
|
+
one + two
|
153
|
+
}"`;
|
154
|
+
});
|
155
|
+
</script>
|
156
|
+
|
157
|
+
<p class="text-gray-600 text-lg mb-4">
|
158
|
+
Интересный факт, что с помощью частичного применения(bind) можно превратить
|
159
|
+
функцию <b>give</b> в <b>источник данных</b>, передав только первый аргумент
|
160
|
+
</p>
|
161
|
+
|
162
|
+
<div class="font-bold mt-8">Смотрите также</div>
|
163
|
+
|
164
|
+
<p class="text-gray-600 text-lg mb-4 dynamic-navigation">
|
165
|
+
<link-dynamic href="/utils/give">give</link-dynamic>
|
166
|
+
<link-dynamic href="/utils/value">value</link-dynamic>
|
167
|
+
</p>
|
@@ -0,0 +1,113 @@
|
|
1
|
+
<h1 class="pb-3 text-xl font-semibold text-gray-600">Класс SourceActive</h1>
|
2
|
+
|
3
|
+
<a
|
4
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Source/SourceActive.ts"
|
5
|
+
target="_blank"
|
6
|
+
class="inline-flex gap-1 items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0 mb-4"
|
7
|
+
>
|
8
|
+
<img
|
9
|
+
src="./assets/img/github_16.jpg"
|
10
|
+
width="16"
|
11
|
+
height="16"
|
12
|
+
/>
|
13
|
+
SourceActive на GitHub
|
14
|
+
</a>
|
15
|
+
|
16
|
+
<p class="text-gray-600 text-lg mb-4">
|
17
|
+
Класс
|
18
|
+
<link-dynamic href="/source">Source</link-dynamic> можно
|
19
|
+
назвать пассивным
|
20
|
+
<link-dynamic href="/terminology/the-source">источником данных</link-dynamic>,
|
21
|
+
потому что мы только вызываем его метод <b>value</b> и надеемся получить
|
22
|
+
данные, либо говорим что нас нужно уведомлять о новых данных. При этом никаких
|
23
|
+
активных действий совершать не требуется
|
24
|
+
</p>
|
25
|
+
|
26
|
+
<p class="text-gray-600 text-lg mb-4">
|
27
|
+
Класс <b>SourceActive</b> можно назвать активным источником данных. Чтобы
|
28
|
+
значение было рассчитано мы должны явно вызывать метод <b>do</b>. Подобные
|
29
|
+
классы полезны в случаях, когда вычисление нужно выполнить не сразу а по
|
30
|
+
событию
|
31
|
+
</p>
|
32
|
+
|
33
|
+
<p class="text-gray-600 text-lg mb-4">
|
34
|
+
Также можно отдельно использовать
|
35
|
+
<link-reloadable
|
36
|
+
target-blank
|
37
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Guest/SourceActive.ts#L9"
|
38
|
+
>ActionType</link-reloadable
|
39
|
+
>
|
40
|
+
интерфейс для объявления своих собственных классов - активных источников
|
41
|
+
данных, имеющих метод do
|
42
|
+
</p>
|
43
|
+
|
44
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Пример 1.</p>
|
45
|
+
<pre
|
46
|
+
class="mb-4"
|
47
|
+
><code class="language-js">import { SourceActive, Patron } from "patron-oop";
|
48
|
+
|
49
|
+
const eur = new SourceActive((_, source) => {
|
50
|
+
source.give("Loading...");
|
51
|
+
fetch("https://www.cbr.ru/scripts/XML_daily.asp")
|
52
|
+
.then((r) => r.text())
|
53
|
+
.then((r) => {
|
54
|
+
const parser = new DOMParser();
|
55
|
+
const doc = parser.parseFromString(r, "application/xml");
|
56
|
+
const eurNode = doc.querySelector('[ID="R01239"] Value');
|
57
|
+
source.give(eurNode.textContent);
|
58
|
+
});
|
59
|
+
});
|
60
|
+
|
61
|
+
eur.value(
|
62
|
+
new Patron((val) => {
|
63
|
+
document.querySelector(".guest-result").textContent = `EUR/RUB = ${val}`;
|
64
|
+
})
|
65
|
+
);
|
66
|
+
|
67
|
+
document
|
68
|
+
.getElementById("get-eur")
|
69
|
+
.addEventListener("click", eur.do.bind(eur));
|
70
|
+
</code></pre>
|
71
|
+
|
72
|
+
<p class="text-gray-600 text-lg mb-1 font-bold">Результат 1.</p>
|
73
|
+
<button
|
74
|
+
class="inline-flex gap-1 items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0 mb-4"
|
75
|
+
id="get-eur"
|
76
|
+
>
|
77
|
+
Get EUR
|
78
|
+
</button>
|
79
|
+
<div class="example mb-4">
|
80
|
+
<span class="guest-result"> Нажмите кнопку "Get EUR" </span>
|
81
|
+
</div>
|
82
|
+
|
83
|
+
<script type="module">
|
84
|
+
import { SourceActive, Patron } from "patron-oop";
|
85
|
+
|
86
|
+
const eur = new SourceActive((_, source) => {
|
87
|
+
source.give("Loading...");
|
88
|
+
fetch("https://www.cbr.ru/scripts/XML_daily.asp")
|
89
|
+
.then((r) => r.text())
|
90
|
+
.then((r) => {
|
91
|
+
const parser = new DOMParser();
|
92
|
+
const doc = parser.parseFromString(r, "application/xml");
|
93
|
+
const eurNode = doc.querySelector('[ID="R01239"] Value');
|
94
|
+
source.give(eurNode.textContent);
|
95
|
+
});
|
96
|
+
});
|
97
|
+
|
98
|
+
eur.value(
|
99
|
+
new Patron((val) => {
|
100
|
+
document.querySelector(".guest-result").textContent = `EUR/RUB = ${val}`;
|
101
|
+
})
|
102
|
+
);
|
103
|
+
|
104
|
+
document
|
105
|
+
.getElementById("get-eur")
|
106
|
+
.addEventListener("click", eur.do.bind(eur));
|
107
|
+
</script>
|
108
|
+
|
109
|
+
<div class="font-bold mt-8">Смотрите также</div>
|
110
|
+
|
111
|
+
<p class="text-gray-600 text-lg mb-4 dynamic-navigation">
|
112
|
+
<link-dynamic href="/source">Source</link-dynamic>
|
113
|
+
</p>
|