dojo/store 是对已存数据的访问和存储的统一接口,dojo/store意图以一个简单、易于使用和扩展的API来,替代、集合和改善 dojo/data 和dojox/storage 。基于HTML5/W3C’s IndexedDB object store API. 原先的dojox/storage 已经被Dojo object store Api兼容。
API
Methods
该API下所有的方法都是可选的,所有的方法都会返回一个promise。(部分在w3c的object store API内还未定论是否提供promise)
(博主:promise可以指派方法做执行成功/失败的回调)
方法名 | 描述 |
---|---|
get(id) | 通过ID检索对象,返回该对象。 |
query(query, options) |
使用提供的query(参数)对store进行查询 返回值为一个数组或者一个promiss, 该promise 必有forEach()、map()、filter()、reduce(),可选的close() 该promise 必有total属性(total同时也可以是promise); options(参数)可能包括下面这些属性,均是可选的:
|
put(object, options) |
保存一个对象(object参数),参数options是可选的,可能有下列值(每一个值都是可选的):
|
add(object, options) | 创建一个新对线,option参数同put() |
remove(id) | 通过ID删除对象 |
getIdentity(object) | 反回该对象的ID,该方法必定是同步的。 |
queryEngine(query, options) |
通过一个query查询,返回一个函数,该函数可以基于一个javascript数组执行这个查询"query"。 改方法可以代替提供更复杂的查询能力,返回的查询函数可以拥有匹配属性,如果该查询被一个对象匹配。 The |
transaction() |
开始事务并返回一个事务对象。 事务对象包括以下: commit() - 在事务中发生的所有变化都提交 abort() - 在事务中发生的所有变化都放弃 注意一个store用户可能不会在使用put,delete等方法前调用transaction(),在这些操作被认为“auto-commit”风格时。 同时,在一个事务中,通知事件是即时的,紧跟着提交操作。也因此,丢弃一个事务,可能要求发送一个新的通知事件去通知数据的回降。 |
getChildren(object, options) |
Returns the children of an object. The 返回一个对象的儿子,配置参数和query()一致。 |
getMetadata(object) |
返回元表数据。 可能包括attribution, cache directives, history, or version information. |
Properties
属性 | 类型 | 描述 |
---|---|---|
idProperty | String | 用来做ID的属性名 |
data | Array of Objects |
如果该store拥有一个缓存对线集合,这个属性可以使之生效。该属性只是引用,所以一个额外的层可以在对象删除时,被完整地清楚掉。 |
Returned Objects
从dojo/store中返回的对象主要被当作普通的hash对象,并且拥有标准的javascript属性来接入他们的数据库和修改他们。无论如何,store返回的对象也会有定义的方法,这些方法并不是他们自己的属性(调用hasOwnProperty(methodName)会返回false),但会是从其中那个一个属性里继承来。这可以确保枚举数据属性的简易性。通常,一个store会选择返回的对象,是 dojo/Stateful 的实例。
Observing Result Sets
当一个store被dojo/store/Observable包裹着时,通过对结果集observe方法,可以监听数据的变化。(结果集是query的返回),observe方法介绍如下:
方法 | 描述 |
---|---|
observe(listener, includeObjectUpdates) |
参数listener是一个函数,这个函数有以下参数: listener(object, removedFrom, insertedInto);
参数 |
close() | 结果集调用该方法后,listener(监听器)不再生效。 |
Modules
下列的存储器(store),存储器的包(store wrapper) 和工具,都是dojo库的一部分。这些提供了一个坚实的基础去构建一个使用存储器的组件,进一步可以去构建更加复杂的存储技术模块。下列的两个核心存储器,是基于经典的内存和服务器的模式的存储器。(in-memory and server-based)
-
一个内存对象,用于保存查询(结果),以及修改、访问客户端内存数据。这可以仅仅由一个简单的javascript数组创建而成。
-
一个面向服务器的JSON/REST对象,通过REST(Representational State Transfer)式的http请求,来保存查询,以及修改、访问数据。这将实现 dojox/data/JsonRestStore,dojox/data/QueryReadStore 和 dojox/data/ServiceStore.的概念和功能。
在新的API中,同样有一个适配存储器,用于兼容旧的dojo/data存储器。
同时,有一个适配存储器允许你以旧的dojo/data存储器来使用新的dojo/store的API:
我们正在将方向转向,通过提供存储器包或者存储器中间件来提供组合的存储器功能。其中几个关键的存储器包:
-
增强存储器的数据检测能力,增加一个observe方法在查询结果集,该方法会通知数据变化。
-
增加存储器的缓存能力,于是一个基本存储器不需要处理缓存问题的能力。
通过一个可以轻易混合和匹配的包,基本存储器实现各种功能。一个常见的模式可能会是这样:
require(["dojo/store/Memory", "dojo/store/Observable"], function(Memory, Observable){
var store = Observable(new Memory({ data: someData }));
});
下面还有两个工具模块:
-
dojo/store/util/SimpleQueryEngine
这是基础的查询引擎(query engine),提供了简单对象哈希表(散列表)过滤器和基于函数的过滤器。
-
这个工具会使用一个数组或者一个带数组返回的promise,并且返回一个结果集对象,该结果集对象拥有标准的迭代方法(
forEach()
,map()
, andfilter()
)
Design
Notification Rational
使用dojo/store里的通知体系(observe),来代替以前dojo/data的通知体系(基于事件),是为了解决几个dojo/data通知体系的问题。
首先,他忽略了一个事实,大部分时间用户只需要监听子集的事件,而且订阅事件是昂贵的。另一方面,在客户端的订阅事件花费很少,全权委托(carte blanche 彗星式派发事件)订阅事件在服务端是非常昂贵的,它强迫服务端发送过多的事件,同时强迫客户端去过滤事件。
同时,事件订阅可以解决一个问题,如果我们使用窗口不理解的方式(这些操作对窗体不透明)去创建或者改变项目时,经常会出现。用grid举一个例子,所有onNew,会增加一行,无论这个增加的新项目是否匹配到查询。而grid它自己完全不知道查询是如何工作的,所以它不能过滤掉这些事件(例如onNew)。现在通过在“查询动作“本身加入通知,通知根据他们如何影响一个给定的查询结果集,可以被解释。(该查询结果集才是窗口最终关心的)
不同的事件名被使用来清晰区分与dojo/data 通知语法的区别。因为影响了查询结果集(无论他们是否已经加入,或者是从一些已存在的查询中出走。),一些独特的事件被定义。同时,onUpdate()被适用于一整个对象,而不是其中的单独的某个属性。
Design Goals
- 人们可以很轻易地实施自己的存储对象,基本上可以很简单地写些什么去与服务器交互,而不需要处理很多dojo/request 调用。更高级的功能可以基于此建立。对于这个策略而言,一个关键点就是非常简单的API,这要求一个最小所需复杂度来实施。
- 维持与dojo/data提供的功能一样的等级。一个存储对象,虽然API所要求必须实施的代码量很少,但有很多部分的代码是可以实施来增强存储器的功能的。可选功能是通过特征检测(检查方法是否存在)来判定是否有效的。拥有很多的可选配置,会将一些实现复杂性从存储器转移者处转移到其它开发人员上,那些希望使用复杂功能的开发人员。无论如何,窗体是最普遍的存储器使用者,而且大部分的开发人员都是使用一个已知配置,已知道功能的存储器。通常,如果他们知道他们正在使用一个同步存储器,与存储器的交互将会变得非常简单。每一个方法都应该是可选的,而且一个方法的实现标识着支持一个功能。还有,通常要求至少要实现get() 和 query()方法,一个存储器如果没有读的能力就太弱了,这是显而易见的。
- 每一个方法都可以用同步或者异步来实现。异步和同步的接口是一致的,区别是同步返回结果,异步返回承诺(promise)。接口要求不能调用其它已知的特定回调(没理解)。
- 通过query 或者 get 从数据返回的对象,必须是一个标准的javasScript对象,因此可以通过经典方法去访问和修改值。