2021SC@SDUSC
这个文件夹名字看起来像是控制器的主页部分。实际上代表了什么含义呢?这就要靠我们的分析去探索了。
我们猜测这是测试的相关代码。(那么为什么不写成test而是写成拼音的ceshi呢,要知道这是一个不好的习惯。)
开头就是很长的一段代码,让我们一点点拆解。
const fs = require('fs');
开头的require调用include 几乎完全一样,除了处理失败的方式不同之外。require 在出错时产生 E_COMPILE_ERROR 级别的错误。换句话说将导致脚本中止而 include 只产生警告(E_WARNING),脚本会继续运行。
module.exports = class extends think.Controller {}
https://www.cnblogs.com/fayin/p/6831071.html介绍了module.exports的用处:CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。require方法用于加载模块。这也可以解释上面为何调用require方法。
https://thinkjs.org/zh-cn/doc/3.0/controller.html解释了think.Controller的作用。MVC 模型中,控制器是用户请求的逻辑处理部分。比如:将用户相关的操作都放在 user.js 里,每一个操作就是里面一个 Action。项目中的 controller 需要继承 think.Controller 类,这样能使用一些内置的方法。当然项目中可以创建一些通用的基类,然后实际的 controller 都继承自这个基类。
之后的定义其中有几个async函数。具体解释见这里https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function,我这里只把介绍搬运过来:async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。await 关键字 只能放在 async 函数内部, await关键字的作用 就是获取 Promise中返回的内容, 获取的是Promise函数中resolve或者reject的值
async fetchAction() {
const res = await this.fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png');
// console.log(res);
// const dest = fs.createWriteStream('./octocat.png');
// res.body.pipe(dest);
this.header('Content-Type', 'image/png');
return this.body = res.body;
}
这一段是“获取”的动作,如上文所示使用await关键字获取资源,并在最后返回标题和图片。
async donatesAction() {
return this.body = 'donates';
}
这一段是定义了一个“捐赠”的动作,返回结果是把内容body换成捐赠相关的内容。
async emailAction() {
const transport = {
service: 'qq',
auth: {
user: 'arterli@qq.com', // your account
pass: 'vxheoipkldjgbhgi' // authorization code, not the email password
}
};
const options = {
from: 'arterli@qq.com', // sender address
to: 'cmswing@126.com', // list of receivers
subject: 'this is subject', // subject line
html: '<b>this is HTML content <img src="cid:00000001"/></b>' // html content
};
const send = await this.sendEmail(transport, options).then(info => {
console.log(info);
}, err => {
console.log(err);
});
console.log(send);
return this.body = 'emial';
}
这一段是定义了一个邮件的页面并且设置了选项(并且是不是最后把email拼错了!);邮件的收件人,发件人,内容,打印信息,如果错误会打印返回情况。总体看来是一个普通的发送邮件功能。
cookAction() {
// this.cookie("hz", 'sfs|dfg|fdsfs');
// $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
// $orderSn = $yCode[intval(date('Y')) - 2011] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
const d = new Date();
const ycode = ['C', 'M', 'S', 'W', 'I', 'N', 'G', 'N', 'E', 'T'];
// return this.body= ycode[this.moment().format('YYYY')-2017]+ (d.getMonth()+1).toString(16).toUpperCase()+this.moment().format('DD')+m.substr(8);
const m = new Date().getTime().toString();
return this.body = think._.padEnd('1', 10, '0') + m.substr(8);
}
先不考虑注释的功能,看起来内容是对日期时间(有个getTime函数)做出某种处理。padEnd函数是补全字符串的作用,详情见这里https://www.zhangxinxu.com/wordpress/2018/07/js-padstart-padend/。据此猜测是对时间处理成规定格式。不得不说使用PadEnd要比注释里之前使用的方式要简洁明了许多的。
async addAction() {
const data = { group_id: '0',
name: '',
title: 'fdsafsafa',
description: '',
type: '2',
cover_id: '0',
keyname: '',
link_id: '0',
display: '1',
'date|||deadline': '',
view: '0',
comment: '0',
level: '0',
'date|||create_time': '',
bookmark: '0',
template: '',
pid: '0',
topid: '0',
model_id: '2',
category_id: '1',
uid: '1',
content: '<p>请填写内容...</p>',
position: 0,
deadline: 0,
create_time: 1504000783284,
update_time: 1504000783284,
status: 1,
id: 251 };
return await this.model('document_ttt').add(data);
}
以上是一段测试的添加内容代码,看起来是把各项参数写进去了,来检测是否正常显示。从中我们也可以看出,一个添加动作需要多少参数。
ipAction() {
return this.body = this.ip;
}
ip相关。值得注意的是在src/bootstrap也出现过ip相关操作。
async extAction() {
console.log(parse_config_attr(think.config('ext.attachment.loactionurl'), '@')[1]);
return this.body = this.config('ext.qq.appkey');
}
ext文件夹里有许多与外界api交际的地方,此处可以视作对api调用的测试。此处的一个函数parse_config_attr,这里有更多的使用例子:https://vimsky.com/examples/detail/php-ex-----parse_config_attr.html
async hooksAction() {
// 带 $hook_type 参数的 视图钩子调用, 参数1,参数2,...{'$hook_type':1},如果由多个参数,{'$hook_type':1} 放最后一个。
await this.hook('adminArticleEdit', '风的撒风的撒风的撒发达富啊222', '的撒风大师傅撒', {'$hook_type': 1});
// 带 $hook_key 参数的 视图钩子调用, 参数1,参数2,...{'$hook_key':'aaaa'},如果由多个参数,{'$hook_key':'aaaa'} 放最后一个。
await this.hook('adminArticleEdit', 'aaaa', '的撒风大师傅撒', {'$hook_key': 'aaaa'});
await this.hook('adminArticleEdit', 'bbbb', '的撒风大师傅撒', {'$hook_key': 'bbbb'});
// 带 $hook_key 和 $hook_type 参数的 视图钩子调用, 参数1,参数2,...{'$hook_key':'bbbb','$hook_type':2},如果由多个参数,{'$hook_key':'bbbb','$hook_type':2} 放最后一个。
await this.hook('adminArticleEdit', 'bbbb', '的撒风大师傅撒', {'$hook_key': 'bbbb', '$hook_type': 2});
// 普通调用
await this.hook('adminArticleEdit', {'$hook_key2': 'bbbb', '$hook_type2': 2});
return this.display();
}
让我们忽略这些脸滚键盘般的测试参数,总之得出的是hook,钩子调用的测试。
async cacheAction() {
const data = await this.model('cmswing/ext').extcache('editor', 'setting');
// console.log(data);
return this.body = data;
}
data获得了编辑器和设置的缓存,由return将其展示出来。
async topicsAction() {
const list = await this.model('document_picture').where({id: ['!=', 311]}).select();
for (const v of list) {
const arr = [];
if (v.pictureurls) {
for (const vv of v.pictureurls.split(',')) {
const obj = {};
obj.id = vv;
obj.name = vv;
obj.src = vv;
obj.info = vv;
arr.push(obj);
}
}
console.log(arr);
const data = {atlas: JSON.stringify(arr)};
await this.model('document_picture').where({id: v.id}).update(data);
}
return this.body = 22;
}
主题的测试代码,令人疑惑的是为什么返回值是22。总之遍历了特定情况的list,并展示。
看到这里,这个文件的作用已经很明了了:一个测试用的文件,测试从钩子到邮件发送等功能,并将结果放在body中展示或者打印出来。属于在开发和修改过程中用到的文件,虽然最终呈现结果时可能关系不大,但还是很重要的部分。
可是,ceshi.js这个名字真的好吗……行吧……