使用新的 when.js 3.2.2 构建 Spring Data REST 的前端

工程 | Greg L. Turnquist | 2014 年 6 月 2 日 | ...

Spring 社区的各位,大家好!

Roy Clarkson 和我将在今年的 SpringOne 2014 大会上做一个名为 Spring Data REST - Data Meets Hypermedia 的演讲。我们将探讨如何快速弥合强大的 Spring Data 后端与支持超媒体的 RESTful 前端之间的差距。

在演讲的一部分中,我们将深入研究一个 JavaScript 前端,该前端允许用户拍照并将其上传到网站。该网站会反过来从后端获取图像。仅凭这一点并不难,这要归功于 Spring Data REST 提供的功能齐全的 RESTful API。

但是,直接获取多个图像效率不高,并且容易冻结 Web 浏览器。感谢我们团队中的 CujoJS 成员(Brian CavalierJohn 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 转换为 GET promise 的数组,获取每个项目的实际图像。如果没有 _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() 结束。 itemsWithImageswhen.all 提供,是一个大小相等的数组,其中包含每个 promise 的结果。

顺便说一句:如果您不知道...使用 promise 时的规则 #1 是 then() 函数调用必须返回一个对象(将被包装为 promise)或 promise 本身。如果您打算实际使用结果并完成它,请改用 done()

如果您是 JavaScript 新手,这可能看起来需要吸收很多东西。但是作为一个 JavaScript 新手,我发现此 API 使我可以轻松地表达我想做的事情。

如果您想了解更多信息,请务必注册 今年 SpringOne 的演讲!我们将研究此照片拍摄应用程序的桌面版本。我们还将深入研究移动友好的浏览器页面和本机移动应用程序,它们都可以让您使用手机的摄像头拍照并上传到该网站。

干杯!

获取 Spring 新闻简报

通过 Spring 新闻简报保持联系

订阅

取得领先

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中为 OpenJDK™、Spring 和 Apache Tomcat® 提供支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部