CesiumJS 对需要网络请求的一切资源都进行了统一的封装,也就是 Resource
类。
在 XHR 技术横行的年代,就出现过 ajax 这种神器,但是 Cesium 团队选择了自己封装 XHR。后来 ES6 出现了 Promise API,axios 再次封装了 XHR,但是 Cesium 团队对这种底层的改动非常敏感,也是最近一年(2021~2022年)才把 var
改为了 const/let
,把 when.js
改为了原生 Promise,把 ""/''
字符串部分改为了 `` 这种反引号字符串,因此自封装的 XHR 就没有改动。
所以,虽然可能不太常用,我认为还是可以了解了解这套 Resource API
的。
1. 资源封装与请求封装
Resource
集成了一些通用的请求方法,以及一些辅助的函数,譬如判断 blob 的支持、处理 Url(修改QueryString、获取基地址等)等。不过,真正发起请求,还是得从 Request
和 RequestScheduler
这两个类说起。
1.1. 请求的封装 - Request 与其调度器
Request
代表一个具体的请求,RequestScheduler
则是调度器。有人说为什么要整个调度类和调度器类,直接让 Resource
发起 XHR 请求不就行了吗?
这与 CesiumJS 的数据调度算法有关,有的请求并不是马上随更新过程就发出的,有的是需要延迟请求的(优先级不同),这时候请求调度器 RequestScheduler
就凸显了作用。
Request
类一般以 Resource
对象字段存在:
function Resource(options) {
/* ... */
this.request = defaultValue(options.request, new Request());
/* ... */
}
在需要使用的时候,会把 Resource
对象上的信息交给 Request
对象:
Resource.prototype.fetch = function (options) {
options = defaultClone(options, {});
options.method = "GET";
return this._makeRequest(options);
};
Resource.prototype._makeRequest = function (options) {
/* ... */
request.url = resource.url;
request.requestFunction = function () {/* ... */};
const promise = RequestScheduler.request(request);
/* ...返回请求的数据... */
};
1.2. 资源类 - Resource
你可以用很多东西来实例化一个 Resource
,你也可以在公开的文档中看到很多参数是“Resource”类型的,例如几个很常见的数据类:
/**
* @param {Resource|String|Promise<Resource>|Promise<String>} options.url The url to a tileset JSON file.
*/
function Cesium3DTileset(options) {/* ... */}
/**
* @param {String|Resource} options.url The url to the .gltf or .glb file.
*/
ModelExperimental.fromGltf = function (options) {/* ... */}
/**
* @param {Resource|String|Object} data A url, GeoJSON object, or TopoJSON object to be loaded.
*/
GeoJsonDataSource.load = function (data, options) {/* ... */}
你用这些信息实例化一个 Resource
:
- 资源的网络相对/绝对路径
Resource
实例本身- base64 字符串(DataUri) / blob 字符串
在各种数据的 API 中也允许你传入不同的参数,例如 glTF 数据允许你传递文件路径、glTF JSON 本身甚至是自己请求下来的 gltf/glb 文件的二进制流,详见本系列文章的第 6 篇。
Resource
类有很多个发起请求的方法,有实例上的,也有静态的,在 1.4 小节会列举。静态方法会 new 一个 Resource
实例,然后调用其对应的实例方法:
Resource.fetchJson = function (options) {
const resource = new Resource(options);
return resource.fetchJson(); // 返回 Promise<object>
};
在现在 axios 或浏览器原生 Fetch API
已经如此通用的环境下,已经很少有需要创建 Resource
对象的需求了。源码中一般会使用 Resource.createIfNeeded()
来创建资源对象,在测试用例中,创建 ktx2 文件资源的代码如下:
const resource = Resource.createIfNeeded("./Data/