Sails库

Author Avatar
A Man Has No Name 7月 31, 2017
  • 在其它设备中阅读本文章

一个JS库

Model以及ORM的配置

  1. config/connections.js 配置连接数据库信息
  2. config/models.js 配置model使用到的connection信息
  3. 创建一个model,有两个参数要注意
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /**
    * Assets.js
    *
    * @description :: TODO: You might write a short summary of how this model works and what it represents here.
    * @docs :: http://sailsjs.org/documentation/concepts/models-and-orm/models
    */
    module.exports = {
    connection: 'mysqlServer',// 我们可以在配置文件中,使用默认的数据库连接方式,也可以在此处自定义
    tableName: 'assets', // 我们可以自定义需要查询的表
    autoCreatedAt: false, // 注意此处,默认是开启的,如果你是mysql,又没有这个字段,记住关掉,否则它会再查询的时候,自动查询此字段
    autoUpdatedAt: false, // 同上
    attributes: {
    id: {
    type: 'integer',
    primaryKey: true,
    required: true
    },
    public_ip: {
    type: 'string'
    },
    main_category_id: {
    type: 'integer'
    },
    inner_ip: {
    type: 'string'
    },
    platform_id: {
    type: 'integer'
    }
    }
    };

常用命令

  1. sails console

    启动一个命令行工具,可以在console界面,访问sails app的信息,比如models,services,包括下划线访问,比如(sails.util._)

1
2
3
4
5
$ sails console
sails> sails.util._.keys(sails.config)
sails> var lodash = sails.util._;
sails> lodash.keys(sails.config);

访问model:

1
2
3
4
5
6
7
sails> User.create({name: 'Brian', password: 'sailsRules'}).exec(console.log)
undefined
sails> null { name: 'Brian',
password: 'sailsRules',
createdAt: "2014-08-07T04:29:21.447Z",
updatedAt: "2014-08-07T04:29:21.447Z",
id: 1 }

查看代码结构等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sails> sails
|> [a lifted Sails app on port 1337]
\___/ For help, see: http://sailsjs.org/documentation/concepts/
Tip: Use `sails.config` to access your app's runtime configuration.
1 Models:
User
1 Controllers:
UserController
20 Hooks:
moduleloader,logger,request,orm,views,blueprints,responses,controllers,sockets,p
ubsub,policies,services,csrf,cors,i18n,userconfig,session,grunt,http,projecthooks
sails>

  1. sails generate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建一个App, 同sails new <path/to/folder>
$ sails generate new <appName>
// 在App中的创建 Foo Controller 和 Foo Model
$ sails generate <appName> <foo>
// 创建model foo 中的字段以及类型
$ sails generate model <foo> [attribute1:type1, attribute2:type2 ... ]
// 创建controller foo中的action
$ sails generate controller <foo> [action1, action2, ...]
// 创建adapter
$ sails generate adapter <foo>
  1. sails new
1
2
3
4
// 创建一个sails项目 到目录里
$ sails new <path/to/folder>
//创建sails项目到当前目录
$ sails new .
  1. sails lift
    • –dev 默认在dev模式下进行
    • –prod 在production模式下运行
    • –port 在某一个端口下运行
    • –verbose 输出调试信息
    • –silly 打开特别详细的日志

Policies, 登陆,鉴权

policies 文件一般都放在 api/policies 文件夹下。每一个policies文件必须包含一个方法。
当请求进来的时候,以中间件的形式,在你的controller之前运行。这样你就可以任意组织多个policies方法,用于鉴权。墙裂建议每一个中间件,只做一件事!!!

  1. 创建一个policies
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// policies/canWrite.js
module.exports = function canWrite (req, res, next) {
var targetFolderId = req.param('id');
// If the requesting user is not logged in, then they are _never_ allowed to write.
// No reason to continue-- we can go ahead and bail out now.
if (!req.session.me) {
return res.redirect('/login');
}
// Check the database to see if a permission record exists which matches both the
// target folder id, the appropriate "type", and the id of the logged-in user.
Permission.findOne({
folder: targetFolderId,
user: req.session.me,
type: 'write'
})
.exec(function (err, permission) {
// Unexpected error occurred-- use the app's default error (500) handler.
//
// > We do this because this should never happen, and if it does, it means there
// > is probably something wrong with our database, and we want to know about it!)
if (err) { return res.serverError(err); }
// No "write" permission record exists linking this user to this folder.
// Maybe they got removed from it? Or maybe they never had permission in the first place...
if (!permission) {
return res.redirect('/login');
}
// If we made it all the way down here, looks like everything's ok, so we'll let the user through.
// (from here, the next policy or the controller action will run)
return next();
});
};
  1. 通过policies鉴权一个controller

sails 中通过配置 ==config/policies.js==. 比如

1
2
3
4
5
6
7
8
9
10
// config/policies.js
{
ProfileController: {
// 访问ProfileController的edit,必须要登陆
edit: 'isLoggedIn'
// create 方法,必须要是isAdmin,且isLoggedIn
create: ['isAdmin', 'isLoggedIn']
}
}

对所有方法设置权限

1
2
3
4
5
6
7
8
{
// 'isLoggedIn' 默认所有方法方法,必须登陆
'*': 'isLoggedIn',
ProfileController: {
// 必须满足 'isAdmin', 但是不一定要满足 'isLoggedIn'~~~
'foo': 'isAdmin'
}
}

==监控如果服务器文件有改动的办法==

⚠️虚拟机中不行

  1. 安装forever npm install -g forever
  2. forever -w start app.js
  3. 添加忽略文件.foreverignore ,并且添加护理内容

    1
    2
    3
    **/.tmp/**
    **/views/**
    **/assets/**
  4. 查看进程状态 forever list , 想要查看日志信息 forever logs [index|scriptName]

  5. 如果在虚拟机中报错,且报错信息是 ==Waiting…Fatal error: watch ENOSPC==, 那么在虚拟机中执行
    1
    $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

Service

services 可以在Sails的任何地方使用,比如ClientService 用来与ucenter进行交互

1
2
3
4
5
6
7
8
9
10
//options: 是一个字典,传递的参数在这里
/*
* done: 是一个回调, 而且只有在异步执行的情况下需要。
* 如果是异步的,那么当他被调用的时候,一个回调函数就会传进来。
*/
module.exports = {
ucenterClient: function (options, done) {
}
}

理解Promise

用来处理回调问题,它会在方法之后添加then,catch,或者finally,方法
避免出现无限回调的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
const request = require('request-promise');
var options = ClientService.ucenterClient(params);
var promise = request(options);
promise.then(
(body) => {
return res.send('成功');
},
(err) => {
return res.send('失败');
}
);

自定义返回

1
2
3
4
5
6
7
8
foo: function(req, res) {
if (!req.param('id')) {
res.status(400);
res.view('400', {message: 'Sorry, you need to tell us the ID of the FOO you want!'});
}
...
}

监听文件修改,并且自动重启服务配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// tasks/config/watch.js
module.exports = function(grunt) {
/*注意这里是用来监听文件修改的*/
grunt.config.set('watch', {
//如果需要监听你的项目文件变动,那么在这里添加配置
assets: {
// Assets to watch:
files: ['assets/**/*', 'tasks/pipeline.js', '!**/node_modules/**', 'config/**/*'],
// When assets are changed:
tasks: ['syncAssets' , 'linkAssets' ]
},
//如果文件有修改,那么重新编译文件(不是重启)
options: {
livereload: true
},
});
grunt.loadNpmTasks('grunt-contrib-watch');
};

Route 路由配置

1
2
3
4
5
6
7
8
9
10
11
12
13
// config/routes.js
module.exports.routes = {
//只处理Get,请求
'get /signup': { view: 'conversion/signup' },
//只处理Post请求
'post /signup': 'AuthController.processSignup',
//Get请求,并且zhi ding指定view地址
'get /login': { view: 'portal/login' },
'post /login': 'AuthController.processLogin',
'/logout': 'AuthController.logout',
//Get请求,并且指定action
'get /me': 'UserController.profile'
}

多个Promise调用的时候,会有报错

Warning: a promise was created in a handler at vagrant/test/sails/api/controllers/UserController.js:31:25 but was not returned from it, see http://goo.gl/rRqMUw
at new Promise (/vagrant/test/sails/node_modules/bluebird/js/release/promise.js:77:14)
at Request.plumbing.init (/vagrant/test/sails/node_modules/request-promise-core/lib/plumbing.js:36:28)

那么,是说明,promise then需要一个返回值,那么你必须返回一个有效的值,不能写成 return ; 可以写成return null;

一个js效率问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 1:
var c = function(){
this.foo = function() {
console.log('哈哈哈哈');
}
}
// 2:
var c = function(){};
c.prototype.foo = function(){
console.log('哈哈哈哈哈');
}
var r = [];
for ( i=0; i< 1000000; i++ ) {
r.push(new c());
}
//经研究发现,2的效率比1高很多

Sails CRSF

在Views from中添加 <%= csrf %>就可以了

Sails Model支持的方法

  1. count, 汇总
1
2
3
4
User.count({name:'Flynn'}).exec(function countCB(error, found) {
console.log('有 ' + found + ' 个叫 "Flynn"的用户');
});
  1. destroy, 删除
  2. create, 新建
  3. find, 查找
  4. findOrCreat, 查找第一个条件,如果不存在,就新建一条
1
2
3
User.findOrCreate({name:'Walter'}, {name:'Jessie'}).exec(function createFindCB(error, createdOrFoundRecords){
console.log('不是 Walter, 那就是Jessie');
});
  1. query ,只针对Mysql 使用原生sql查询 ‘select * …..’
  2. findOne, 查找yi tiao一条
  3. stream, 这个是以流的是形式返回(不建议使用)
  4. update, 更新
  5. native, 这是mongo专用的原生SQL查询
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Pet.native(function(err, collection) {
    if (err) return res.serverError(err);
    collection.find({}, {
    name: true
    }).toArray(function (err, results) {
    if (err) return res.serverError(err);
    return res.ok(results);
    });
    });

MySQL 原生SQL查询 同时添加Promise

1
2
3
4
5
6
7
8
9
var Promise = require('bluebird');
var serviceQuery = Promise.promisify(Services.query);
serviceQuery.query('select * from services').then(
).catch(
);

Sails WebSocket

在页面中引入js

1
2
3
4
5
6
7
// 客户端脚本(layout.ejs)
// 引入js
<script type="text/javascript" src="/js/dependencies/sails.io.js"></script>
<script type="text/javascript>
</script>

添加Controller

1
2
// WorkerController