ArcGIS Maps SDK for JavaScript是基于现代的响应式设计的,所有的变更都可以被追踪。为了更好的了解SDK的使用,让我们首先从理解响应式开始。
响应式编程
响应式编程(Reactive Programming,简称RP)并不是一个新鲜的概念,而是一个存在已久的编程范式。通过面向数据流的设计以及变更检查与传播的心智模型,使得响应式编程能够更加便捷的表达数据流及他们之间的影响。 近些年来,尤其是在前端JavaScript编程中,随着React、Vue等基于响应式设计的框架流行,响应式编程被越来越多的开发者所理解和接受,在前端丰富的交互式场景中,响应式编程的设计思想可以更容易地描述UI界面中发生的变化并跟踪产生这些变化的来源,相比过去主流的jQuery等侧重指令性和过程描述性的编程模型,响应式编程在大型的复杂前端应用构建中愈加体现了在程序员心智负担上的优势。 尽管响应式编程是如此的接近人类的思维模式,然而从程序设计上来说却并不简单。对于初次接触响应式编程的入门者来说,通常极易混淆关于响应式的几个不同的概念。在不同的场景中,这些名词对于不同的人可能指代了不同的意义。其次,由于响应式设计在代码层面的抽象,使得局部代码的细节并不如命令式代码结构清晰。事实上如果我们能穿过知识的迷雾,会发现事实上响应式设计具有更清晰的逻辑结构,只是通过简短的局部示例来解读全局的设计思路并不容易,有时候一不小心就会陷入理论主义的陷阱。
RxJS与FRP
部分经验丰富的开发人员或多或少接触过函数响应式编程(Functional Reactive Programming,简称FRP)。其中,RxJS是JavaScript领域最为著名的FRP实践。然而,响应式编程与RxJS中提出的以Stream为中心的响应式并不完全等同。他们两者之间具有某些思路上的相似性,但并不能简单的认为响应式编程就是使用RxJS。
细粒度响应式设计
在JavaScript编程中,要实现细粒度的响应式设计通常是基于类似Promise这样的元对象实现的,我们不能从最底层的String或者Number这样的对象开始实现,这是由于这一类对象没有编排能力。
一段响应式设计的程序可以被理解为有向的图或者更简单的说就像水管,它具有这样的特性,当任何的变更从其中的某个节点发生,这些变更将会通过管道蔓延到所有的节点。同步是这一过程中最重要的问题,我们需要能精确的控制变更在每个独立的节点上发生的时机。
-> 我们从了解JavaScript响应式设计中的元对象开始。
Signals
信号(Signals)是响应式系统重最为重要的部分。信号可以被抽象理解为一个值(value),以及相关的处理器(getter、setter)。虽然在更为学术性的场景中被称为Signals,在部分框架中也有时被叫做Observables、Atoms、Subjects或者Refs,这往往指代同一类。
const [count, setCount] = createSignal(0);
// read value
const val = count(); // 0
// set value
setCount(10);
console.log(count()); // 10
这里最重要的不是了解信号所存储的值,而是get和set函数,他们可以执行任意的代码,从而让我们对更新的传播具有控制能力。在基于JavaScript的框架中,大部分采用函数来实现,然而ES6以后新的Proxy也提供可以另外一种实现方式。
Reactions
孤立的谈论信号通常并不能带来实际的意义,而与信号共同构成响应式基础的就是行为(Reactions)。在部分框架中也有时被叫做Effects、Autoruns、Watches或者Computeds,行为主要观察信号,并在信号的值发生改变时执行。
这通常是通过包装函数来实现的,这些函数在初始化时获得执行,并在信号变化时重新执行。 信号提供的自定义get函数为行为的观察提供了基础,当信号的get函数被执行时,行为函数的包装器得以通过订阅或者挂载等机制将自身与信号进行关联。
这里重要的是,信号可以存储任意类型的值,而行为函数同样可以在运行时做任何的事。其次,行为函数的运行通常与信号的变更是同步执行的。
对于任意的响应式系统来说,信号和行为就是它最核心的部分,也可以称之为被观察者与观察者。整个系统中其他的行为都可以构建在这两者之上。
接下来我们深入更多的细节。