2.2

## 控制器

### 定义控制器

``````'use strict';

import Base from './base.js';

export default class extends Base {
/**
* index action
* @return {Promise} []
*/
indexAction(){
//auto render template file index_index.html
return this.display();
}
}
``````

``````'use strict';

var Base = require('./base.js');

module.exports = think.controller(Base, {
/**
* index action
* @return {Promise} []
*/
indexAction: function(self){
//auto render template file index_index.html
return self.display();
}
});
``````

### 使用 async/await

##### ES7 方式
``````'use strict';

import Base from './base.js';

export default class extends Base {
/**
* index action
* @return {Promise} []
*/
async indexAction(){
let model = this.model('user');
let data = await model.select();
return this.success(data);
}
}
``````
##### 动态创建类的方式
``````'use strict';

var Base = require('./base.js');

module.exports = think.controller(Base, {
/**
* index action
* @return {Promise} []
*/
indexAction: async function(){
var model = this.model('user');
var data = await model.select();
return this.success(data);
}
});
``````

### init 方法

ES6 里的 class 有 constructor 方法，但动态创建的类就没有该方法了，为了统一初始化执行的方法，将该方法统一定义为 `init`

##### ES6 方式

``````'use strict';

import Base from './base.js';

export default class extends Base {
init(http){
super.init(http); //调用父类的init方法
...
}
}
``````
##### 动态创建类方式
``````'use strict';

var Base = require('./base.js');

module.exports = think.controller(Base, {
init: function(http){
this.super('init', http); //调用父类的init方法
...
}
});
``````

`init` 方法里需要调用父类的 init 方法，并将参数 `http` 传递进去。

### 前置操作 __before

ThinkJS 支持前置操作，方法名为 `__before`，该方法会在具体的 Action 调用之前自动调用。如果前置操作里阻止了后续代码继续执行，则不会调用具体的 Action，这样可以提前结束请求。

##### ES6 方式

``````'use strict';

import Base from './base.js';

export default class extends Base {
/**
* 前置方法
* @return {Promise} []
*/
__before(){
...
}
}
``````

### Action

``````'use strict';

import Base from './base.js';

export default class extends Base {
/**
* 获取详细信息
* @return {Promise} []
*/
detailAction(self){
...
}
}
``````

### 后置操作 __after

ThinkJS 支持后置操作，方法名为 `__after`，该方法会在具体的 Action 调用之后执行。如果具体的 Action 里阻止了后续的代码继续执行，则后置操作不会调用。

### 空操作 __call

``````'use strict';

import Base from './base.js';

export default class extends Base {
/**
* @return {Promise} []
*/
__call(){
...
}
}
``````

### 模型实例化

``````export default class extends think.controller.base {
indexAction(){
let model = this.model('user'); //实例化模型 user
...
}
}
``````

model 方法更多使用方式请见 API -> think.model.base

### http 对象

Action 里如果想获取该对象，可以通过 `this.http` 来获取。

``````'use strict';

import Base from './base.js';

export default class extends Base {
indexAction(){
let http = this.http;
}
}
``````

### this 作用域的问题

Node.js 里经常有很多异步操作，而异步操作常见的处理方式是使用回调函数或者 Promise。这些处理方式都会增加一层作用域，导致在回调函数内无法直接使用 `this`，简单的处理办法是在顶部定义一个变量，将 `this` 赋值给这个变量，然后在回调函数内使用这个变量。如：

``````module.exports = think.controller({
indexAction: function(){
var self = this; //这里将 this 赋值给变量 self，然后在后面的回调函数里都使用 self
this.model('user').find().then(function(data){
return self.model('article').where({user_id: data.id}).select();
}).then(function(data){
self.success(data);
})
}
})
``````

``````module.exports = think.controller({
//参数 self 等同于 var self = this
indexAction: function(self){
this.model('user').find().then(function(data){
return self.model('article').where({user_id: data.id}).select();
}).then(function(data){
self.success(data);
})
}
})
``````

##### 使用 Generator Function
``````export default class extends think.controller.base {
* indexAction(){
let data = yield this.model('user').find();
let result = yield this.model('article').where({user_id: data.id}).select();
this.success(result);
}
}
``````
##### 使用 Arrow Function
``````module.exports = think.controller({
indexAction: function(){
this.model('user').find().then(data => {
return this.model('article').where({user_id: data.id}).select();
}).then(data => {
this.success(data);
})
}
})
``````

### JSON 输出

#### 输出正常的 JSON

``````export default class extends think.controller.base {
indexAction(){
let data = {name: "thinkjs"};
this.success(data);
}
}
``````

#### 输出含有错误信息的 JSON

``````export default class extends think.controller.base {
indexAction(){
this.fail(1000, 'connect error'); //指定错误号和错误信息
}
}
``````

##### 配置错误号和错误信息

``````export default {
10001: 'get data error'
}
``````

##### 友好的错误号

``````export default {
GET_DATA_ERROR: [1234, 'get data error'] //key 必须为大写字符或者下划线才有效
}
``````

#### 格式配置

``````export default {
key: 'errno', //error number
msg: 'errmsg', //error message
}
``````

#### 输出不包含错误信息的 JSON

``````export default class extends think.controller.base {
indexAction(){
this.json({name: 'thinkjs'});
}
}
``````

### 常用功能

#### 获取 GET 参数

``````export default class extends think.controller.base {
indexAction(){
let name = this.get('name');
let allParams = this.get(); //获取所有 GET 参数
}
}
``````

#### 获取 POST 参数

``````export default class extends think.controller.base {
indexAction(){
let name = this.post('name');
let allParams = this.post(); //获取所有 POST 参数
}
}
``````

#### 获取上传的文件

``````export default class extends think.controller.base {
indexAction(){
let file = this.file('image');
let allFiles = this.file(); //获取所有上传的文件
}
}
``````

``````{
fieldName: 'file', //表单字段名称
originalFilename: filename, //原始的文件名
path: filepath, //文件保存的临时路径，使用时需要将其移动到项目里的目录，否则请求结束时会被删除
size: 1000 //文件大小
}
``````

#### 更多方法

• `isGet()` 当前是否是 GET 请求
• `isPost()` 当前是否是 POST 请求
• `isAjax()` 是否是 AJAX 请求
• `ip()` 获取请求用户的 ip
• `redirect(url)` 跳转到一个 url
• `write(data)` 输出数据，会自动调用 JSON.stringify
• `end(data)` 结束当前的 http 请求
• `json(data)` 输出 JSON 数据，自动发送 JSON 相关的 Content-Type
• `jsonp(data)` 输出 JSONP 数据，请求参数名默认为 `callback`
• `success(data)` 输出一个正常的 JSON 数据，数据格式为 `{errno: 0, errmsg: "", data: data}`
• `fail(errno, errmsg, data)` 输出一个错误的 JSON 数据，数据格式为 `{errno: errno_value, errmsg: string, data: data}`
• `download(file)` 下载文件
• `assign(name, value)` 设置模版变量
• `display()` 输出一个模版
• `fetch()` 渲染模版并获取内容
• `cookie(name, value)` 获取或者设置 cookie
• `session(name, value)` 获取或者设置 session
• `header(name, value)` 获取或者设置 header
• `action(name, data)` 调用其他 Controller 的方法，可以跨模块
• `model(name, options)` 获取模型实例
{"ft_lang_label":"__label__zh","ft_lang_prob":0.6877123,"math_prob":0.5171283,"size":7753,"snap":"2019-35-2019-39","text_gpt3_token_len":3214,"char_repetition_ratio":0.14982578,"word_repetition_ratio":0.21618497,"special_character_ratio":0.26157618,"punctuation_ratio":0.20188531,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9612391,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-08-23T10:20:23Z\",\"WARC-Record-ID\":\"<urn:uuid:f067cc42-530e-4be3-a383-64839f283a46>\",\"Content-Length\":\"42779\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:a3153940-a5dd-4d1b-a9c0-bee7136bec74>\",\"WARC-Concurrent-To\":\"<urn:uuid:73b9756d-f200-43d7-9ccc-080ffe9a2a32>\",\"WARC-IP-Address\":\"139.199.24.222\",\"WARC-Target-URI\":\"https://thinkjs.org/zh-cn/doc/2.2/controller.html\",\"WARC-Payload-Digest\":\"sha1:OJF7SFSD4XP2435VTXLYUAEFRZQ2FFRD\",\"WARC-Block-Digest\":\"sha1:2Z4BCYBNAYSGMJAQAJ2DF3SEKLBVJ7YX\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-35/CC-MAIN-2019-35_segments_1566027318243.40_warc_CC-MAIN-20190823083811-20190823105811-00394.warc.gz\"}"}