走在前沿
VMware 提供培训和认证,以加速您的进步。
了解更多Spring 社区成员们,您好!
我和Roy Clarkson将在今年的 SpringOne 2014 大会上发表题为Spring Data REST - 数据与超媒体的演讲。我们将探讨如何快速弥合功能强大的 Spring Data 后端与支持超媒体的 RESTful 前端之间的差距。
在演讲的一部分中,我们将深入探讨一个 JavaScript 前端,它允许用户拍摄照片并将其上传到网站。该网站随后会从后端获取图像。由于 Spring Data REST 提供了功能齐全的 RESTful API,因此这本身并不难。
但是,直接获取多个图像效率不高,并且容易导致 Web 浏览器冻结。感谢我们团队中的 CujoJS 成员(Brian Cavalier 和John Hann),我能够使用最近发布的 when.js 模块并编写出更流畅的用户体验。
下面的片段展示了 rest.js 与通过 when.js 实现的 Promise 相结合的核心用法,以及它如何使编写易读且功能强大的代码变得非常简单。
首先,我们引入一些关键模块
var rest = require('rest');
var when = require('when');
var defaultRequest = require('rest/interceptor/defaultRequest');
var mime = require('rest/interceptor/mime');
var hateoas = require('rest/interceptor/hateoas');
然后,我们使用 mime
拦截器和 hateoas
拦截器配置一个 api
对象,并将其配置为将 Accept
标头默认设置为 application/hal+json
,以便 Spring Data REST 使用 HAL 进行通信。
var api = rest
.wrap(mime)
.wrap(hateoas)
.wrap(defaultRequest, {headers: {'Accept': 'application/hal+json'}});
通过这种配置,我们可以进行一些 RESTful 调用来获取图像数组,而不会影响用户体验。
when.all(api({
method: 'GET',
path: gallery._links.items.href,
params: {projection: "noImages"}
}).then(function (response) {
if (response.entity._embedded) {
return response.entity._embedded.items.map(function (itemWithoutImage) {
return api({path: itemWithoutImage._links.self.href})
})
} else {
return [];
}
})).done(function(itemsWithImages) {
itemsWithImages.forEach(function(item) {
items[item._links.self.href] = item.entity;
nestedTable.append(createItemRowForGallery(item.entity, gallery));
})
})
那么发生了什么呢?让我们看一下每个小片段并了解正在发生的事情。
api({
method: 'GET',
path: gallery._links.items.href,
params: {projection: "noImages"}
})
这正在进行一个调用以检索与此特定 画廊相关的 项目数组。它返回一个 Promise,为我们提供了一些不错的选项。
注意:它使用
?projection=noImages
来获取项目 URI 列表,而不包含图像数据。(一次性获取十个 2MB 的图像!)
.then(function (response) {
...
})
此函数然后获取 URI 列表并将获取其各个图像的工作分解。
if (response.entity._embedded) {
return response.entity._embedded.items.map(function (itemWithoutImage) {
return api({path: itemWithoutImage._links.self.href})
})
} else {
return [];
}
在 then
函数内部,代码查找 _embedded
数据,如果存在,则将其转换为 1 对 1 的无图像项目数组,并获取每个项目的实际图像。如果没有 _embedded
数据,则返回一个空数组。
when.all(
...
).done(function(itemsWithImages) {
itemsWithImages.forEach(function(item) {
items[item._links.self.href] = item.entity;
nestedTable.append(createItemRowForGallery(item.entity, gallery));
})
})
获取图像数据的 Promise 数组使用when.all进行包装,这是一个方便的函数,它将在每个 Promise 完成之前等待。
由于我们打算通过在屏幕上显示来使用所有这些 GET
的输出,因此我们使用 done()
完成操作。itemsWithImages
(由 when.all
提供)是一个大小相等的数组,包含每个 Promise 的结果。
顺便说一句:如果您不知道...使用 Promise 时规则 #1 是,then() 函数调用必须返回一个对象(将被包装为 Promise)或一个 Promise 本身。如果您打算实际使用结果并完成操作,请改用done()。
如果您刚接触 JavaScript,这可能看起来有点难以理解。但作为我自己也是 JavaScript 新手,我发现这个 API 让我能够轻松地表达我想做的事情。
如果您想了解更多信息,请务必注册参加今年的 SpringOne 大会上的演讲!我们将查看此拍照应用程序的桌面版本。我们还将深入探讨移动友好的浏览器页面和原生移动应用程序,两者都允许您使用手机的相机拍摄照片并上传到网站。
干杯!