sails 自动创建方法前加async 为啥都带 async

使用 Sails 构建和部署一个基本 Web 应用程序
此内容是该系列 # 部分中的第 # 部分: 面向 JavaScript 开发人员的 Sails.js 指南,第 1 部分http://www.ibm.com/search/csass/search/?q=wa-build-deploy-web-app-sailsjs&dws=cndw&ibm-search.x=12&ibm-search.y=17&ibm-search=Search&sn=dw&lang=zh&cc=CN&ddr=&en=utf&lo=zh&hpp=20敬请期待该系列的后续内容。此内容是该系列的一部分:面向 JavaScript 开发人员的 Sails.js 指南,第 1 部分敬请期待该系列的后续内容。
您是否曾经在一个食品店的奶酪货架旁徘徊,被来自全世界的奶酪引人入胜的包装搞得不知所措?这也没什么,但麻烦在于决定将哪种奶酪带回家。奶酪选择如此丰富,以至于成为了选择悖论 的完美例子,该原则表明没有选择是件坏事,但拥有太多选择同样是件坏事,而且有时会导致用户完全放弃选择。寻找 Node.js 框架或库的开发人员就面临着这个问题,这是一个虚拟的有钱人窘境。很难知道从如此多的选项中选择哪一个,更不用说如何开始使用一个 Node.js
框架了,或者是哪些因素将帮助您决定它是否是正确的选择。选择 Sails.js考虑到过多的选项,在选择 Sails.js 之前,我需要艰难地排除一些备选选项。我喜欢 Sails,因为它包含的一些想法已使 Rails
框架变得如此成功,同时保持着一个明显的 Node.js 风格。具体来讲,Sails 使用分层开发和约定优于配置(convention over
configuration),这两种开发技术已被 Rails 和类似的框架普及。Sails 还集成了其他一些 Node.js
包作为关键组件,这意味着您不需要从头学习该框架。另一个优势是,事实上 Sails.js 的文档在不断改进,这是我在任何开源项目中都要寻找的一个关键指标。在第一部分中,我将重点介绍 Sails 如何实现分层开发。未来的几部分将介绍约定优于配置和使用 Sails 编码的其他便捷性。新 MVC“对传统 MVC
架构的这种重新配置,实现了架构师和开发人员长久以来在应用服务器中寻找的东西:一个包含业务逻辑和验证的单一位置,以及一个用于多个客户端的通用接口。”Sails 的分层开发方法与许多传统 Web 开发人员可能期望的不同。事实上,Sails 是新兴的框架种类中的一个,这些框架通过调优 MVC 而重新定义了 Web
应用程序开发的前景。与传统的 MVC 架构中将 MVC 组件放在服务器上不同,Sails 将模型和控制器放在服务器上,而视图位于客户端层。Sails 还将 “视图”
视为一种更加一般性的概念;它可以是 HTML,但它也可以是一个在原生 iOS 或 Android 中编写的移动应用程序。不同于由服务器向客户端传送回 HTML,Sails 仅传送数据(通常为 JSON 或 XML 格式)。然后,客户端(一个移动应用程序或使用 AngularJS 等客户端
JavaScript 框架编写的单页 Web 应用程序)使用该数据,并以最适合客户端的方式呈现它。对于大部分客户端,数据表示格式将为 JSON,因为许多单页 Web
和移动客户端都是使用 JavaScript 编写的,而且可以轻松地使用 JSON。而且如果有必要,采用像 XML 这样的不同的数据表示格式也不难。对传统 MVC
架构的这种重新配置,实现了架构师和开发人员长久以来在应用服务器中寻找的东西:一个包含业务逻辑和验证的位置,以及一个用于多个客户端的通用接口。服务器仅需要以一种可被客户端识别的表示设计数据元素,此方法提供了一种通过
HTTP 端点执行传统业务逻辑和数据验证的轻松方式。HTTP API
示例应用程序这种新架构(我称之为 HTTP API)类似于 RESTful 风格,但它实际上不是 REST — 至少依据 Roy Fielding 的
来讲不是。REST 依靠超媒体的交换作为表示应用程序状态的主要手段(这就是 Hypertext As The Engine Of
Application State 或 HATEOAS 原则 — 可能是迄今为止发明的最差劲的缩写)。但 HTTP API 系统放弃了 REST
提供的一定的灵活性和 “通用客户端” 功能,以换取更简单的模型。不同于 REST 系统,HTTP API 客户端需要它们与之通信的系统的一定的推断性知识。它们需要提前知道预期的结果和可用的端点。这与 REST
架构相反,但我发现它所换来的简单性物有所值。在一个 HTTP API 中,客户端与服务器之间的所有通信在 HTTP 上发生。对于示例应用程序,我将使用 JSON 作为交换的数据格式,使用标准 HTTP
洞察来表示操作(GET 表示读取,POST 表示插入,PUT 表示更新,DELETE 表示删除)。我还将使用 HTTP
头部作为传达带外信息的机制,比如身份验证数据等。但是,我仍会将一些状态数据存储在服务器端(与传统的 REST 设计相反),而且交换的数据将全部为 JSON
并假定为特定于此系统。HTTP API 的使用者示例 — 移动应用程序、单页 JavaScript 应用程序或者甚至其他想访问这里包含的数据的服务器 —
将知道我将向它们发回的 JSON 类型。这不同于更具有 REST 风格的超文本/HATEOAS 的关注点,后者演示任何应用程序都应能够 “发现”
发回的信息。更重要的是,使用者将知道它们的数据将发送到、被检索或修改的后续 HTTP 端点。在评估 Sails.js 时,我花了一些时间来试验它。所以言归正传,让我们开始了解 Sails 吧。需要的准备工作:前提软件和设置我希望您对 REST 和 RESTful 架构的原理和术语具有一定的了解;您不需要是发烧友,但您应熟悉 “原生地” 使用 HTTP 来提交 GET 请求、POST
请求等。您不应被查看动态的 HTTP 请求的想法吓到。我还假设您熟悉 JavaScript、Node.js 和 npm(JavaScript 代码和库的包管理器)。您应在所选的开发环境上安装了
Node.js,知道如何在本地运行 Node.js 应用程序,并能够自行使用 "npm-install" 安装软件包。尽管查阅所谓的 现代
JavaScript 很有帮助(具体来讲,Douglas Crockford 在
或它所催生的许多图书或教程之一中描述的 JavaScript),但事实上,您仅需要 JavaScript
的实用知识即可开始使用 Sails。对于您的开发环境,请确保您机器上的 Node.js 是最新的(截至编写本文时,我的版本是 0.12.7),而且您安装了最新的 npm 版本(我的版本是
2.12.1)。尽管 Node.js 社区明显在尝试保持各个版本向后兼容,但无法保证我在这里编写的代码就适用于该技术的早期版本。一经出售,概不负责。安装 Sails.js 和
MongoDB使用 Sails.js 唯一需要的安装是在全局上将它安装到 npm 缓存,就像这样:npm install -g Sails.js。完成之后,您将拥有一个实用程序命令 sails 可供使用。像 npm 一样,sails 是一个使用
JavaScript 为 Node.js 编写的命令行实用程序。它充当着使用 Sails.js 框架执行多种操作的单一来源实用程序 —
比如创建一个新应用程序,运行该应用程序,在调试循环中运行该应用程序,为该应用程序生成新组件,等等。通过 npm 安装 Sails.js 时,一定要使用
-g 选项。否则,它将仅安装在当前的项目目录中,而且这是该实用程序真正需要全局化的少有情况之一。在等待 Sails.js 框架下载和安装期间,请花片刻时间确保您已在开发环境中设置了 MongoDB。如果没有设置,现在正是
的好时机。请注意,Sails.js 使用的不仅仅是一个 MongoDB 后端;事实上,Sails.js
开箱即用地使用了一种基于磁盘的轻量型格式。这不是用于生产用途的推荐设置,但非常适合像我们这样的示例。到达本系列中使用 MongoDB
的部分还需要一段时间,但在我使用它时您一定很高兴拥有它。这是目前需要的基本设置。在本教程后面将本地应用程序部署到 Bluemix 云时,您将需要向资源组合中添加一个
和一个 。检查安装Sails.js 完成安装了吗?使用命令 sails version 验证它。截至编写本文时,Sails.js 的最新版本是 0.11.0。只要上面的命令生成的输出不是错误,就表明 Sails 已安装并准备好使用。Sails.js 显示 "Hello,
world!"根据惯例,程序员在学习一种新语言或环境时所做的第一件事是使用该语言编写最简单的程序:一个 Hello World 应用程序。幸运的是,Sails 生成了一个 Hello
World 作为您创建一个新应用程序时的基本应用程序框架。我可使用此应用程序确认 Sails 基础架构有效。为了向敏捷开发战略致敬,我还将该框架部署到云(在本例中为
Bluemix)中,作为 “尽早发布,经常发布” 战略的一部分。创建一个基本的 Sails.js 应用程序获取一个新 Sails.js 应用程序非常简单。请注意,默认情况下,该框架将生成一个更传统的 Web 应用程序,其中服务器生成的 HTML
会发回到客户端。尽管这本身很有用,但如果目标是构建一个对客户端不可知的 HTTP API,我希望确保没有意外 "泄露"
将客户端与服务器捆绑在一起。为此,最佳方式是构建一个在项目任何地方都没有客户端组件的服务器。在 Sails.js 中,这非常简单,只需将您的默认配置设置为
--no-frontend。使用 --no-frontend 选项的不足之处是,我没有可视的方式来确认该框架有效。我希望在将应用程序部署到 Bluemix
时执行该验证。所以在第一部分中,我将创建拥有漂亮的 HTTP 前端框架的应用程序,但在未来的几个部分中,我会假设该应用程序构建时未使用任何前端部分(差别仅在于生成的
views 目录中填充的内容,所以它没有可能看起来那么复杂)。闲话少说。我们实际操作一下吧!从开发机器上您想要代码所在的目录,通过 sails 命令行发出一个 new
命令,然后命名您的应用程序:sails new hello-sails。完成这一步后,Sails 将等待片刻,然后回复一条类似这样的消息:"Created a new Sails app
'hello-sails'!"(如果返回了任何其他信息,可能您的 Sails.js 安装某处出错了。)在目标目录中(根据应用程序名称推断而来),您会看到
Sails.js 生成了许多目录和文件。我将在整个系列文章中更详细地介绍其中大部分内容。就现在而言,您只需熟悉 Sails 应用程序的基本知识。一般而言,可以安全地假设创建框架不会有任何问题(只要没人接触它),但知道如何在本地运行该应用程序会很有帮助。我们通过一个 "sails lift"
来开始我们的操作。图 1. 在本地运行 Sails.js非常漂亮,不是吗?就个人而言,我喜欢这种颜色的用法,此外这也正是 ASCII 作品令人印象深刻的显示形式。更重要的是,这个小型 ASCII 图像确认 Node.js
正成功地在本地机器的端口 1337 上运行我们搭建的应用程序。在浏览器中访问它,将出现默认的 Sails.js 网页,其中包含连接回主要 Sails
主页和文档的链接。将 Sails.js
部署到云在本地机器上运行与将代码部署到生产(或准生产)服务器不同,这时就需要使用云。对于本系列文章,我将使用 Bluemix 作为云主机。它看起来非常合适,而且 Bluemix
是一个容易用于托管基于 Node.js 的应用程序的平台。Bluemix 也恰好基于 Cloud Foundry,所以如果您还没有
(cf),现在是时候安装它了。您将希望在托管您的 Sails.js
代码的同一台机器上运行它。安装客户端后,运行 cf--version 来验证安装;在编写本文时,回送的版本是 6.12.2。如前所述,您还需要一个
来将应用程序部署到
Bluemix。获得您的凭据后,登录到 Bluemix 并将代码从您本地的 hello-sails 目录推送到 Bluemix 云。清单 1. 使用 cf 推送到
BluemixTeds-MBP15:hello-sails ted$ cf login
API endpoint: https://api.ng.bluemix.net
Authenticating...
Select an org (or press enter to skip):
1. developerWorks
Targeted org developerWorks
Targeted space Ted Neward
API endpoint:
https://api.ng.bluemix.net (API version: 2.27.0)
developerWorks
Ted Newardcf 工具也需要知道要用于部署的 API 端点。如果 cf 无法确定该端点,您可通过命令 cf api
api.ng.bluemix.net 手动设置它 (api.ng.bluemix.net)。两个有用的文件登录并设置 API 端点后,您将使用 cf push 将搭建的 Sails.js 应用程序部署到云。Cloud Foundry
仅需要一些参数即可正确地部署该应用程序。无需反复键入这些参数(它们会烦人地不断增加),可创建一个清单文件 (manifest.yml)。这将包含一些信息,比如要在
Bluemix 云上使用的应用程序名称,要用于一个子域的主机名(如果它与应用程序名称不同),要为执行保留多少 RAM,等等。示例的简单清单文件:---
applications:
- name: tedneward-sailsIntro
host: tedneward-sailsIntro
memory: 256M
command: node app.jsCloud Foundry 能识别的另一个有用文件是
.cfignore。它包含不应从本地应用程序推送到云的文件或目录列表。就现在而言,记录该信息只是为了未来参考。有了该清单文件,仅剩下执行 cf push 来让 push
命令完成自己的任务了(来自此命令的输出有时非常长,因为代码必须打包、上传、解包,然后安装在云实例上,这进而意味着需要在云实例上运行一次 npm
install,这会生成大量结果。因此,这里仅显示了前 20 行和最后 6 行输出)。清单 2. 使用 cf push 推送到
BluemixUsing manifest file /Users/ted/Projects/sails-intro/code/hello-sails/manifest.yml
Updating app tedneward-sailsIntro in org developerWorks / space Ted Neward as ...
Using route tedneward-sailsIntro.mybluemix.net
Uploading tedneward-sailsIntro...
Uploading app files from: /Users/ted/Projects/sails-intro/code/hello-sails
Uploading 31M, 11773 files
Done uploading
Stopping app tedneward-sailsIntro in org developerWorks / space Ted Neward as ...
Starting app tedneward-sailsIntro in org developerWorks / space Ted Neward as ...
-----& Downloaded app package (24M)
-----& Downloaded app buildpack cache (18M)
-----& IBM SDK for Node.js Buildpack v2.5-6
Based on Cloud Foundry Node.js Buildpack v1.5.0
-----& Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=true
NODE_MODULES_CACHE=true
-----& Installing binaries
engines.node (package.json):
unspecified
engines.npm (package.json):
unspecified (use default)
App tedneward-sailsIntro was started using this command `node app.js`
Showing health and status for app tedneward-sailsIntro in org developerWorks / space Ted Neward as ...
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: tedneward-sailsIntro.mybluemix.net
last uploaded: Mon Oct 5 01:36:54 UTC 2015
stack: lucid64
buildpack: SDK for Node.js(TM) (ibm-node.js-0.12.7)假设您已正确上传和安装所有组件,您应在 Bluemix 上看到一个新子域(在我的例子中,该子域为
http://tedneward-sailsIntro.mybluemix.net)。新子域将生成 Sails.js 示例欢迎页面来响应一个 HTTP
GET / 请求。结束语有了该框架,我就准备好开始扩展和改进示例应用程序了。得益于目前完成的工作,我将能够在每次完成一个新部分时,将新代码部署到 Bluemix 云。请记住原则 “不断发布”
— 或换种说法
“尽早发布,经常发布”。每次我将代码推送到服务器供其他人使用,我都在给其他人创造机会来寻找错误,确认我的代码在朝正确的方向发展,等等。使用一个被广泛接受的云基础使发布变得非常轻松,因为我已提前完成了大部分工作。使用一个简单的
cf push,Sails 应用程序的最新版本将时刻等待着 HTTP 客户端找到和使用它。下一篇文章将介绍 Sails.js 模型。在介绍模型的过程中,我们还会介绍大量 Sails 约定,称为蓝图或 Sails Blueprint API。就像它的灵感之源
Rails 一样,Sails 喜欢约定高过配置,这意味着我将能够构建模型,获得一些现成的有用功能,而无需编写大量配置文件或代码。我现在已有一个框架,但在接下来的几个教程中形成的示例应用程序将是一个博客引擎 — 经过了一定的修改。不同于将该引擎构建为一个传统的服务器端 Web
应用程序,我会将它开发为一个 HTTP API。该 API 将我需要的所有技术都打包到后端,将客户端代码留给有人喜欢编写的前端工具来解决。现在是时候暂停一下了。对于该框架的名称,我们不想说 “再见”,说 “一路平安” 会更合适。
下载资源 (sailsjs1-code.zip | 168KB)相关主题访问
来进一步了解 Sails.js 的方方面面。您会在
的文档页面上找到有关它的大量信息。使用这个便捷的
开始使用 Bluemix,其中包含一个专门介绍 Node.js 开发的专题。(一个 HTTP API
CMS 系统)是本系列教程中使用的示例应用程序的灵感来源。
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=http://www.ibm.com/developerworks/js/artrating/SITE_ID=10Zone=Web development, Open source, 移动开发, Cloud computingArticleID=1022982ArticleTitle=面向 JavaScript 开发人员的 Sails.js 指南,第 1 部分: 使用 Sails 构建和部署一个基本 Web 应用程序publish-date=模型和蓝图
此内容是该系列 # 部分中的第 # 部分: 面向 JavaScript 开发人员的 Sails.js 指南,第 2 部分http://www.ibm.com/search/csass/search/?q=wa-build-deploy-web-app-sailsjs&dws=cndw&ibm-search.x=12&ibm-search.y=17&ibm-search=Search&sn=dw&lang=zh&cc=CN&ddr=&en=utf&lo=zh&hpp=20敬请期待该系列的后续内容。此内容是该系列的一部分:面向 JavaScript 开发人员的 Sails.js 指南,第 2 部分敬请期待该系列的后续内容。
欢迎回来,水手们!您已经在
中初步了解 Sails.js,在开发环境中设置了一个本地安装,创建了一个 Sails.js 应用程序的框架,并在 IBM Bluemix®
上启动它。开发框架应用程序有助于了解 Sails.js 中的编程的基础知识。现在我们将撇开 “Hello World” 应用程序的简单乐趣,创建一个更加真实的示例应用程序。您会回想起示例应用程序是一个博客 API,其中集成了传统 REST 架构的部分元素。该博客应用程序将保存并发布博客条目,还将执行典型的博客操作,比如跟踪评论,生成和显示 RSS
提要等。HTTP API 设计有助于建立一个稳定的可扩展后端,而视图取决于移动、桌面或 Web 客户端。博客 API
拥有相对较小的用例集合,至少在开始的时候是这样。用户能够创建任何数量的博客条目,而且每个条目都将包含标题、正文、标记和作者。这些条目还将显示一个创建时间戳和另一个更新时间戳。在以后,您将重构该应用程序并添加更多的功能,但现在我们将保持它的简单性。 建模该应用程序从头开发 MVC
应用程序时,您可能会考虑应该从模型还是从控制器元素开始。在必要时,不仅可以从控制器开始,也可以从控制器构建完整的应用程序:您只需为应用程序的每个功能定义一个控制器,并与数据库传输数据。您始终可以在以后重构该应用程序,从您的控制器架构中提取模型。在 Sails.js 中,从模型开始的效率更高一些。不仅 Sails 模型容易设计,Sails 还提供了一系列称为蓝图
的控制器路由,它们会自动应用于不同的模型类型。您需要做的只是在 Sails 中定义模型,Sails 将自动为该模型的基本数据存储和检索功能设置 API 路由和功能。Sails.js 的模型优先方法也非常适合 HTTP API 应用程序的 RESTful 设计。REST 希望公开资源,您已在模型中提前定义了这些资源。为博客 API 建模很容易:只需定义应用程序所需的模型类型,Sails
默认情况下会为它们建立蓝图。在拥有模型和蓝图后,还要定义它们之间的关系,并添加一些独立控制器来处理整个应用程序的行为。对于该博客
API,我们需要一个独立控制器来查找评价最高的博客条目,还需要另一个控制器来提供博客条目的 RSS 提要。一般化的建模开发第一个 Sails 模型之前,需要确定如何 建模您的数据:您将使用关系实体、文档实体还是其他实体?在 Sails 中,答案是视具体情况而定。正常情况下,在使用其他软件堆栈(比如 MEAN 堆栈)时,数据存储引擎是堆栈的重点部分。因此,您使用该堆栈为应用程序定义的条目是根据数据存储引擎自己的偏好严格建模的。例如,在使用
Rails 时,您将构建与关系实体紧密关联的模型;使用 MEAN 时,您将构建面向文档的模型。不同于其他一些堆栈,Sails 从数据存储引擎中抽象出数据操作。因此,您可以选择 MySQL 和 Postgres 等关系数据库,MongoDB 等文档数据库,Redis
等键值存储,甚至可以选择内存型或自定义的简单磁盘存储格式。此抽象在数据存储引擎的选择上为您提供了很高的灵活性,但也为您留下了一些一般性选项。(这是功能还是限制完全取决于您的决定。)Waterline:Sails ORMSails 抽象数据层的核心是它的内置 ORM,名为 。作为一个数据访问层,Waterline 支持几乎所有数据库,包括关系和非关系 (NoSQL) 数据库。尽管 Waterline
对任何类型数据存储的支持满足了避免供应商锁定的诉求,但一般化也消除了针对特定类型的数据层进行优化的机会。幸运的是,您不需要 结合使用 Waterline 和 Sails。所以如果您认为 Waterline 不适合针对 MongoDB 的数据建模,那么您可以悄悄使用
Mongoose。然后,您可以直接将 Sails 应用程序与 MongoDB 和 Mongoose 绑定在一起。考虑到这项提醒,我们暂时假设您在为一个一般化的数据层建模。基于磁盘的持久性在开发周期的早期,您或许不想太多地考虑持久性层,甚至是像您从 MongoDB 获得的一般化且松散类型的持久性层一样。这意味着除了坚持采用 Waterline 之外,您将为 Sails
使用默认的持久性层。这是一个纯粹的本地系统,Sails 称之为 “sails-disk”
数据库,它将对象存储在内存中,直到可以将它们写入磁盘。实际存储格式非常简单,但几乎不相关,因为您只能将它用于设计项目原型,自行实验或在文章中演示
Sails。使用默认系统为您提供了以创造性的方式思考模型的最终状态的空间,但又不会让您太快地迷失在构建这种复杂东西的细节上。因为没有模式,所以在您准备好后执行重构将会非常容易。创建 Sails 模型的过程是一种类似对象的体验,但不是您可能熟悉的富域模型。Sails
模型缺少基于对象的编程的一些常见功能。但是,如果您了解其他框架中的对象关系映射,就可能发现 Sails
与其中的体验差不多。在开始建立对象之间的关系时,您将面临它们之间的权衡。就现在而言,我们首先会定义一些基本的数据类型。建模一个博客条目花点时间想想您希望在博客条目中看到哪些功能。您不需要立即规划和实现每个组件,但在开始编码之前制定一个基本计划是一个不错的想法。作为一个模型,BlogEntry
至少需要一个标题和正文。因为人们经常编辑和检索博客条目,所以一个不错的想法是添加一个 created 字段来表示首次创建该条目的时间,添加一个
updated 字段来表示最后编辑时间。您将在以后添加 tags 和 author 等其他字段。我们现在首先来查看前 4 个字段。Sails:生成!您已选定了一个基本模式并决定让 Sails 将模型存储到磁盘中。接下来,您将告诉 Sails 生成您的数据模型和关联的控制器的脚手架。首先调用命令 sails
generate api BlogEntry。该命令将创建两个文件:BlogEntry.js(可在
/api/models 目录中找到)和 BlogEntryController.js(在
/api/controllers 目录中)。我们将 BlogEntryController 留到以后讨论。现在来看看 BlogEntry 模型:清单 1. 一个空模型/**
* BlogEntry.js
* @description :: TODO: ...
:: http://sailsjs.org/#!documentation/models
module.exports = {
attributes: {
};该模型显然需要一些属性。使用您的默认 sails-disk 数据库,首先定义 BlogEntry 类型。请注意,您没有添加
created 和 updated 属性,因为 Sails 会自动添加它们:清单 2. 将字段添加到模型中/**
* BlogEntry.js
* @description :: A blog entry stored in the CMS.
:: http://sailsjs.org/#!documentation/models
module.exports = {
attributes: {
type: 'string'
type: 'string'
};接下来,Sails 会定义一个基于 BlogEntry 模型的 BlogEntry 类(任何种类;位于所有 JavaScript
后)。该模型的每个实例都将拥有您在它之上定义的初始博客条目属性。将属性添加到模型中Sails 支持的属性远不止字符串类型,还包括一些方便的标准,比如
'string'、'text'、'integer'、'float'、'date'、'datetime'、'boolean'、'binary'、'array'
和 'json'。其中许多属性也支持依据需求执行自定义(例如用于验证或实现唯一性)。碰巧,清单 2 中的模型缺少一些关键内容。如果两篇博客文章拥有同一个标题会怎样?这是一个完全合理的假设场景,而且很容易通过向模型添加主键字段来管理。这听起来像
'integer' 属性的工作,如下所示。清单 3. 将主键添加到模型中/**
* BlogEntry.js
* @description :: A blog entry stored in the CMS.
:: http://sailsjs.org/#!documentation/models
module.exports = {
attributes: {
type: 'integer'
// ... the rest
};这是 Waterline 模型管理不同数据存储的方法变得有趣的地方,因为 Waterline 必须能够向数据库描述数据模型中的任何属性。例如,Waterline 需要知道该 ID
是否将是主键。如果它是(大部分情况下是这样),Waterline 会将 RDBMS 中的 id 列标记为 PRIMARY KEY,将
MongoDB 中的一个 id 属性改为 _id,等等。Sails 允许您使用 JavaScript 的简单的对象式语法来提供元属性,比如:清单 4. 将元属性添加到模型中/**
* BlogEntry.js
* @description :: A blog entry stored in the CMS.
:: http://sailsjs.org/#!documentation/models
module.exports = {
attributes: {
type: 'integer',
primaryKey: true
type: 'string',
required: true,
defaultsTo: ''
type: 'string',
required: true,
defaultsTo: ''
};这是一种非常直观的描述格式。转换为人类语言后,上述代码将类似于:id 是一个整数类型的属性,primaryKey 元属性被设置为
true。以下是 Sails 中使用的常见元属性的快速参考:email 验证数据元素是否是电子邮件地址。如果未指定值,defaultsTo 会将该值设置为 use。autoIncrement 只能用在整数属性上。unique 验证此属性是否在所有实例上是唯一的。primaryKey 表明该属性将用作模型的主键。enum 表明这个元属性的值是只接受给定属性的值的数组。所以 enum:['Fred', 'Barney', 'Wilma',
'Betty'] 表示仅接受这 4 个值。size 将会设置传递给数据库的大小限制,通常是字符串长度限制。请参阅
文档,了解 Sails 元属性的完整列表。上面的简单模型对基本的博客引擎已足够了。保存您的 BlogEntry.js 文件,然后执行 sails lift
在本地运行它。严肃地讲,请完成这一步后再前进到下一步。中止、重试和忽略发出这个 sails-lift 后,您或许有点震惊。Sails 没有安静愉快地继续执行,它会立刻将以下信息发送到您的控制台:清单 5. safe/alter/drop?Excuse my interruption, but it looks like this app
does not have a project-wide "migrate" setting configured yet.
(perhaps this is the first time you're lifting it with models?)
In short, this setting controls whether/how Sails will attempt to automatically
rebuild the tables/collections/sets/etc. in your database schema.
You can read more about the "migrate" setting here:
http://sailsjs.org/#/documentation/concepts/ORM/model-settings.html?q=migrate
In a production environment (NODE_ENV==="production") Sails always uses
migrate:"safe" to protect inadvertent deletion of your data.
However during development, you have a few other options for convenience:
- never auto-migrate my database(s). I will do it myself (by hand)
2. alter - auto-migrate, but attempt to keep my existing data (experimental)
- wipe/drop ALL my data and rebuild models every time I lift Sails
What would you like Sails to do?现在,您可能注意到的第一件事是,Sails 的错误消息是最容易理解的。这不是唯一的方式:Sails
还会生成其他难以阅读的错误消息,尤其在与我们在一些编程语言中获得的错误相比时。因为您是向新的 BlogEntry 发出的第一个 sails lift 请求,所以 Sails
会问:我应该如何处理将用来存储此模型的底层数据库系统的模式(如果有)?对于许多开发人员,还会停下来思考以下问题:其他 ORM 系统有一些要求您手动编辑和管理数据库模式的基本行为,而 Sails 希望代表您管理这些任务。由于 Sails 无法对 “旧”
模式和 “新” 模式执行任何类型的语义比较,而且在您能进行多大程度的重构才不会让 Sails
无法理解语义方面,可能有些限制,所以选项有点少。将这种模式迁移合并到环境中非常不错,至少在它阻碍您工作或犯错之前是这样的。所以最好花点时间想想您的选择,并始终确保备份了您的代码和数据。与此同时,返回到控制台,Sails 也希望知道它在重构模型时该如何做:safe:假设开发人员将管理所有模式重构。alter:尽可能地在不丢失任何数据的情况下修改现有模式(这肯定存在失败的风险)。drop:从头开始创建新模式。在开发周期的早期阶段,每次都重新构建模型是您的最佳方法,因为您将不断调整模型类型。不用说,您绝不会为生产系统选择此选项。在将应用程序部署到生产中时,您可能需要选择第一个选项,因为大部分组织都对任何可能潜在地截断一个表的操作都很敏感,更别提整个数据库。但是因为您仍在实验并使用
sails-disk 存储系统(它没有任何模式),所以可以随意选择 “drop” 并保持简单性。选择 drop 选项后,您将在控制台中看到熟悉的帆船图案。Sails 在正常运行,是时候开始将数据注入您的模型了 — 但是该如何操作?Blueprints APISails 随带了预定义的 HTTP 端点来支持基本的 CRUD 操作(GET、POST、PUT 和 DELETE)。每个选项都连接到一个从您模型的名称生成的 URL
端点。因此,即使只设置了博客 API 的框架,向 http://localhost:1337/BlogEntry 发出 GET 请求也会返回合法的 JSON
响应,如下所示:图 1. GET /BlogEntry尽管屏幕截图是空的,但上面显示的 JSON 数组告诉我 Sails 蓝图正在运行。在这种情况下,蓝图正在运行为一个 HTTP GET 端点定义的路由。剩余 CRUD
端点不难确定:POST 到 /BlogEntry,这会使用 POST 正文作为要插入的数据来创建一个新的 BlogEntry
对象。PUT 将修改一个现有的 BlogEntry,DELETE 会删除它。(请注意,PUT 和 DELETE 都将切断提交的 HTTP
请求中的主键属性。)在典型的 Web 开发场景中,这可能是您开始编写 curl 命令行脚本的时刻,因为浏览器默认情况下不会执行 PUT 或 DELETE 操作,而是需要一个
HTML 表单来启动 POST 请求。该操作非常单调和无聊,而且(对 Sails 开发人员而言)完全没有必要。除了基本的 4 个 HTTP 端点之外,得益于 Sails
开箱即用地设置的蓝图默认设置,您还可以使用一些 “快捷” 路由使用来自浏览器的 GET 请求将记录放入系统中。举个恰当的例子,如果您在浏览器中访问:/BlogEntry/create?title=%27Fred%27&body=%27Hello world%27&id=1",Sails 将使用以下信息作为响应:图 2. 一个包含一些数据参数的 CREATE毫无疑问,如果您返回并再次发出 GET /BlogEntry 请求,则会显示一个实例。现在您可能注意到,此设置不太像 REST 风格,因为它使用 GET
动词来执行修改数据库的操作。尽管明显违背 REST 系统的规则,但在此刻,它是开发周期中值得拥有的一个不错选项。而且在将系统部署生产中之前,您应该关闭此实例和所有其他自动生成的路由。首先,拥有两种将数据插入系统中的可能方式会导致代码重复(有两个必须创建的端点,例如,如果您对谁可以将新博客条目放入数据库中进行限制)。其次,拥有执行同一种操作的多种方法可能会让将继承您的系统的开发人员混淆。很好地理解这些演示和早期原型设计,一旦经过了早期阶段,它们就没那么有用了。蓝图路由完整的
详细介绍了为 Sails 配置的所有蓝图路由。除了执行创建/插入的快捷路由(您已在上文看到)之外,还有两个自动生成的蓝图路由也值得讨论:PUT /:model/:record 是对记录执行更新的默认路由。GET /:model/:record/update 允许您将要更新的属性指定为查询参数对,比如:GET
/BlogEntry/1/update/title=New%20Title。您可以指定 PUT 请求或 GET “快捷” 请求上的参数,但同样地,应该为了生产用途而关闭该快捷路由。GET /:model 有许多参数可作为查询参数传递给 GET 请求。例如,limit
可用于设置应返回的最大条目数,skip 可用于表明在返回之前跳过了多少个条目。一起使用这两个参数可为大型记录集提供简单的分页支持:当用户在以 50
个记录划分的记录块中移动时,每移动一次就会执行一次 limit=50, skip 0, 50, 100, 150,依此类推。GET 蓝图路由也支持 sort,这允许您指定某个要排序的属性,以及该属性应按升序 (ASC) 还是降序 (DESC)
进行排序。(一定要确保在属性名和顺序之间放入了一个空格,就像这样:?sort=lastName$20ASC。)另一个受支持的参数是 where,它将接受一个 JSON 风格的类似 MongoDB 的谓词,比如
?where={"name":{"contains":"theodore"}}(这是一个 Waterline WHERE 条件对象,Waterline
将针对关系数据库适配器而将它调整为 SQL。)如果要搜索的属性有一个特定的值(无处不在的 SELECT * FROM persons WHERE lastName='Flintstone'
查询),该路由会直接接受它作为查询参数,比如:GET /BlogEntry?title=Greetings%20everybody。考虑到您目前仅编写了十几行代码,这是一组不错的功能。结束语关于在 Sails.js
中建模,还有许多知识需要学习,但现在,已经有足够的新领域供您探索。在下一篇教程中,将进一步了解模型和它们之间的关系;也就是说,将了解许多数据系统中存在的经典的 “1对1”、“1对多”
和 “多对多” 关系。建模关系会使您能够扩展博客 API 来接受评论等信息。但现在,是时候暂停一下了。对于该框架的名称,我们不想说 “再见”,说一路平安
也许会更合适一些。
下载资源 (sailsjs-2-source.zip | 134KB)相关主题访问
以进一步了解
Sails.js 的方方面面。 是
Sails 的默认 ORM。 Waterline
的内置模型方法。与 Sails.js 捆绑在一起的
适配器是一个仅用于预生产用途的持久性对象存储。需要进一步了解 ORM?请参阅 “”(Scott
W. Ambler,developerWorks,2000 年 7 月)。要进一步了解 Ted 对于对象关系阻抗失配的想法,请参阅 “”(TedNeward.com,2006 年 6 月)。为开发人员提供了大量资源。
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=http://www.ibm.com/developerworks/js/artrating/SITE_ID=10Zone=Web development, Open sourceArticleID=1028714ArticleTitle=面向 JavaScript 开发人员的 Sails.js 指南,第 2 部分: 模型和蓝图publish-date=}

我要回帖

更多关于 async异步方法调用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信