forked from CyclejsCN/cyclejs.cn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dialogue.html
200 lines (145 loc) · 8.84 KB
/
dialogue.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
189
190
191
192
193
194
195
196
197
198
199
200
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>Cycle.js - 对话抽象</title>
<!-- Flatdoc -->
<script src='support/vendor/jquery.js'></script>
<script src='support/vendor/highlight.pack.js'></script>
<script src='legacy.js'></script>
<script src='flatdoc.js'></script>
<!-- Algolia's DocSearch main theme -->
<link href='//cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css' rel='stylesheet' />
<!-- Others -->
<script async src="//static.jsbin.com/js/embed.js"></script>
<!-- Flatdoc theme -->
<link href='theme/style.css' rel='stylesheet'>
<script src='theme/script.js'></script>
<link href='support/vendor/highlight-github-gist.css' rel='stylesheet'>
<!-- Meta -->
<meta content="Cycle.js - 对话抽象" property="og:title">
<meta content="一个函数式和响应式的 JavaScript 框架,用来编写前瞻性代码。" name="description">
<!-- Content -->
<script id="markdown" type="text/markdown" src="index.html">
# 对话抽象
## 人机交互
Cycle.js 对[人机交互 (HCI)](https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction)模型介绍了一种[消息传递](https://en.wikipedia.org/wiki/Message_passing)架构。目前大多数前端框架聚焦于 DOM 层的图形用户界面,而当你需要建立任意形式的人机交互时,Cycle.js 是一个更全面而适宜的方案。本章将带你深入洞察 Cycle.js 架构的设计理念。HCI 是一个双向的过程:双方互为倾诉者与倾听者。
![简单的人机交互](img/simple-human-computer.svg)
计算机常常会通过屏幕“说”一些人类可以“听”的可视化的信息。通过不同的设备,计算机可以到达人类不同的感官。另一方面,人类也常常通过操作鼠标或者触摸屏幕对计算机“说”一些指令。
人机交互是一场对话:一次双方之间正在进行的信息交换。
双方都能够“听到”对方,并能够通过他们的设备传达消息。换句话说,我们可以说人类和计算机是处于相互观察状态的,简而言之,正在进行一场对话。我们指出“相互观察”的原因是它与响应式编程相关,并会影响到我们如何模型化这个系统。
> ### 与 Haskell 1.0 相似?
>
> 同样的对话概念可以在 [Haskell 1.0 基于流的 I/O](https://www.haskell.org/definition/haskell-report-1.0.ps.gz) 中找到,其中 `type Dialogue = [Response] -> [Request]` 是和操作系统的交互模型。 `[Response]` 是来自操作系统的信息流(惰性的潜无穷列表(lazy potentially-infinite list),准确来说),`[Request]` 是流向操作系统的信息流。
>
> Cycle.js 的抽象是独立发现于 Haskell 的 I/O 流的。只要方便,我们会试着从 Haskell 的 `Dialogue` 中吸取灵感,但是它们有一些概念上的差别。并不是所有有关 Haskell `Dialogue` 的问题都在 Cycle.js 中存在或会影响到 Cycle.js 的用户,反之亦然。这是由于对执行环境的不同假设和对模型化事件流的不同设计决策。如果你需要有关这个话题的更多细节,推荐下面的跳转谈话,围绕着 Cycle.js 的历史和背后的理论展开:
<p>
<iframe width="100%" height="360" src="https://www.youtube.com/embed/Tkjg179M-Nc" frameborder="0" allowfullscreen></iframe>
</p>
## 作为 I/O 的感知/执行器(senses/actutors)
计算机是由和人类交互的设备组成的。**输出**设备呈现给人们信息,**输入**设备则检测来自人类的活动。人类有**执行器**和**感知**,分别连接着计算机的**输入**和**输出**设备。
![执行器 感知 I/O](img/actuators-senses-input-output.svg)
计算机的**输入**和**输出**表明计算机在人机交互中的角色可以被表达为一个函数。我们的确还不知道在 JavaScript 中什么应该是 `inputDevices` 和 `outputDevices`,但从现在开始,试着欣赏 `computer()` 作为一个纯函数的优雅。
```javascript
function computer(inputDevices) {
// 以某种方式定义 `outputDevices` 的行为
return outputDevices;
}
```
重构和架构仅仅关系到选择正确的函数来组成 `computer()`。
当谈及输入,输出,感知,和执行器时,感知和输入之间的差别变得难以描述,除了前者常与人类相关,而后者常与计算机有相关之外。从计算机的层面上看,麦克风和其驱动程序是它能够**感知**听觉信息的方式。本质上,当我们忽略人体的天然性和计算机器的物理性时,人类和计算机都仅仅是具有感知和执行器的智能体。
```javascript
function computer(senses) {
// 以某种方式定义 `actuators` 的行为
return actuators;
}
```
现在,在这种交互中的智能体是**对称**的了:一个智能体的执行器连接着另一个的感知。反之亦然。
![执行器 感知](img/actuators-senses.svg)
上面的图是对计算机的一种拟人化[anthropomorphism](https://en.wikipedia.org/wiki/Anthropomorphism)。如果我们采用相反的方式,把人类物化为机器,那么人类和计算机都将成为具有输入输出功能的函数。
![HCI 输入 输出](img/hci-inputs-outputs.svg)
这表明人类将成为从感知到执行器的函数。
```javascript
function human(senses) {
// 以某种形式定义 `actuators` 的行为
return actuators;
}
```
> 观看 Andre Staltz 关于**如果把用户看作函数会怎样?** 的谈话,强调了和本章同样的主题。
<p>
<iframe width="100%" height="360" src="https://www.youtube.com/embed/1zj7M1LnJV4" frameborder="0" allowfullscreen></iframe>
</p>
尽管这些抽象似乎是用户界面自然的选择,但仍存在许多问题:
- `感知` (senses) 和 `执行器` (actuators) 的类型是什么?
- 何时调用 `human()` 函数?
- 何时调用 `computer()` 函数?
- 如果一个函数的输出是另一个函数的输入,如何解决这种循环依赖问题 `y = human(x)` 且 `x = computer(y)`?
这些都是驱动着 Cycle.js 核心架构的问题,但为了理解我们的解决方案,我们首先需要理解反应流:在 Cycle.js 中我们用来构建一切的程序块。[继续阅读](streams.html)。
</script>
<!-- Initializer -->
<script>
Flatdoc.run({
fetcher: function(callback) {
callback(null, document.getElementById('markdown').innerHTML);
},
highlight: function (code, value) {
return hljs.highlight(value, code).value;
},
});
</script>
</head>
<body role='flatdoc' class="no-literate">
<div class='header'>
<div class='left'>
<h1><a href="/"><img class="logo" src="img/cyclejs_logo.svg" >Cycle.js</a></h1>
<ul>
<li><a href='getting-started.html'>Documentation</a></li>
<li><a href='api/index.html'>API reference</a></li>
<li><a href='releases.html'>Releases</a></li>
<li><a href='https://github.com/cyclejs/cyclejs'>GitHub</a></li>
</ul>
<input id="docsearch" />
</div>
<div class='right'>
<!-- GitHub buttons: see https://ghbtns.com -->
<iframe src="https://ghbtns.com/github-btn.html?user=cyclejs&repo=cyclejs&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
</div>
</div>
<div class='content-root'>
<div class='menubar'>
<div class='menu section'>
<ul>
<li><a href="getting-started.html" class="level-1 out-link">起步</a></li>
</ul>
<div role='flatdoc-menu'></div>
<ul>
<li><a href="streams.html" class="level-1 out-link">Streams</a></li>
<li><a href="basic-examples.html" class="level-1 out-link">Basic examples</a></li>
<li><a href="model-view-intent.html" class="level-1 out-link">Model-View-Intent</a></li>
<li><a href="components.html" class="level-1 out-link">Components</a></li>
<li><a href="drivers.html" class="level-1 out-link">Drivers</a></li>
</ul>
</div>
</div>
<div role='flatdoc-content' class='content'></div>
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-101243593-1', 'auto');
ga('send', 'pageview');
</script>
<script>
((window.gitter = {}).chat = {}).options = {
room: 'cyclejs/cyclejs'
};
</script>
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
<script src='//cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js'></script>
<script src='docsearch.js'></script>
</body>
</html>