文章目录
  1. 1. 模型设计
    1. 1.1. 问卷类行为的设计
      1. 1.1.1. 问卷模型
    2. 1.2. 问题模型
    3. 1.3. 注册登录页的行为设计
      1. 1.3.1. 基本功能:
      2. 1.3.2. 方案
    4. 1.4. 错误传递/API设计/Error类的设计

这部分主要介绍了网站部分模型和行为的设计

模型设计

问卷类行为的设计

问卷类的设计包括**(M)数据库问卷模型的设计(V)页面基于Jade + json的问卷渲染引擎**

问卷模型包括问卷模型问题模型,其中前者是后者的集合

还有mogoose的API和原生mongodb的CURD文档的学习

问卷模型

属性:标题、描述、权限、问题集合、预留扩展

方法:使用了mongoose驱动提供的公用方法。并没有针对问卷模型封装出专用方法。目前还没有必要,如果以后问卷模型需要更多的有针对性的操作,会考虑将此模型的方法封装出来 。

1
2
3
4
5
6
7
8
9
10
11
12
13
var mongodb = require('./mongodb');
var Schema = mongodb.mongoose.Schema;
var QuizSchema = new Schema ({
title: String, //问卷大标题
discription: String, //问卷描述
authority: Array, //问卷权限
questions:Array //问题组
});
var Quiz = mongodb.mongoose.model("Quiz", QuizSchema);
module.exports = Quiz;

问题模型

属性:id、序号、类型、题干、选项、是否显示评论框、是否显示为必答题、问题提示、预留扩展

方法:同上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var mongodb = require('./mongodb');
var Schema = mongodb.mongoose.Schema;
var QuestionSchema = new Schema ({
id: String, //问题id
index: String, //问题序号
type: String, //问题类型
content: String, //问题题干
area: String, //问题选项
hasDiscuss: Boolean, //是否显示讨论框
isMust: Boolean, //是否为必答题
tips: Array //提示
});
var Question = mongodb.mongoose.model("Question", QuestionSchema);
module.exports = Question;

注册登录页的行为设计

基本功能:

  • 邮箱合法性验证
  • 用户名合法性验证
  • 密码长度验证
  • 密码确认验证
  • 用户num唯一性验证
  • 服务器超时验证
  • 用户友好信息
  • 按钮的锁止与解锁

方案

  • 前端验证

    • 正则表达式

      采用正则表达式来验证邮箱、用户名、密码长度的合法性验证

    • HTML 5新技术

      在下一次技术修改中,将使用HTML 5表单验证提供的新的行为和触发样式 ,来替换上面的方案,不再兼容低版本浏览器。

  • 后端验证

    用于用户num的唯一性验证,基于AJAX技术实现

    • 优化:减少数据库IO请求

      后期应该考虑将邮箱也加入唯一性验证中,因为通知邮件的发送必须唯一。同时要对唯一性验证函数进行修改,最好能传入多组待验证的数据(比如同时验证邮箱和用户num),达到一次数据库请求可以验证多个数据,以减少数据库IO请求

    • 优化:异步请求

      最初,服务器的超时验证时基于同步的。为什么要使用同步呢?因为AJAX的回调函数是异步的。即请求收到之前,在这个异步函数之外,用于接收信息的变量都是false,然后函数据需向下执行,即使请求最后收到,程序也不可能回头再从接收信息的变量往下重走一遍。所以最开始我使用了同步请求来解决这个问题,但是同步很多是否我们是要尽量避免的,还要因为一个小功能而面对复杂的错误处理,实在不值得。 所以最终我把同步请求收到后执行的函数进行了一次包装,并作为回调函数传入公共的AJAX函数中,这样,只有请求收到或超时之后才会运行后面的函数,并添加了try``catch来捕捉情况之外的错误。这样处理之后,我们的AJAX可以使用异步请求了。

    • 优化:服务器超时

      如果在客户端向服务器端认证用户唯一性时,可能会由于网络或服务器问题造成客户端收不到响应。这时应该向客户进行友好提示:服务器超时。

      我们在前端公共库的代码中设置一个定时器,每次AJAX请求发出之后开启,可以传入等待时间和超时提示信息。然后在每次响应收到之后,清除该定时器。

      片段如下:

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
39
40
41
42
43
44
case 'user-num':
var that = this;
numInfo.innerHTML = '正在向服务器确认…';
utils.reg.verifyUserUnique(this.value, function (err, result) {
if (err) {
numInfo.innerHTML = err;
console.log(err);
} else if(result) {
userNumStatus = (utils.reg.verifyUserNum(that.value));
userNumStatus?numInfo.innerHTML = '编号有效':numInfo.innerHTML = '编号格式有误';
console.log(userNumStatus);
} else {
userNumStatus = result;
numInfo.innerHTML = '用户已存在';
}
changeInputStyle.call(that, userNumStatus);
checkStatus();
});
function verifyUserUnique(num, callback) {//公共库中的AJAX公用函数
var xhr = new XMLHttpRequest();
var flag =false;
xhr.open('GET', '/verifyUserUnique?num='+num, true);
var overTimer = utils.common.overTime(4000, '服务器超时', callback);
xhr.onreadystatechange = function () {
if (xhr.readyState==4 && xhr.status==200) {
window.clearTimeout(overTimer);
var res = window.JSON.parse(xhr.responseText);
console.log(res.instance);
if(res.code == '01') {
flag = true;//说明用户不存在,唯一
} else {
flag = false;//说明用户不存在,不唯一
}
typeof(callback) === 'function'?callback(null, flag):callback('typeError', null);
}
};
try {
xhr.send();
} catch (error) {
callback(error);
}
}
  • 公共函数
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
var utils = {
exp: {
userNumReg: /^(AGUI-)(\d+)/,
userNameReg:new RegExp('[A-Za-z0-9_\-\u4e00-\u9fa5]+'),
userEmailReg: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,
userPwReg: /^[\S|\s]{6,16}$/,
userPhoneReg: /^(0|86|17951)?((13[0-9]|15[012356789]|17[05678]|18[0-9]|14[57])[0-9]{8})$/
},
common: {
overTime: function overTime(time, info, callback) {
var str = info;
var overTimer = window.setTimeout(function () {
callback(str+time, null);
}, time);
return overTimer;//返回定时器索引,供清除使用
}
},
reg: {//邮箱/两次密码/客官号正则/唯一性验证ajax
verifyInputEmail: function verifyInputEmail(em) {
return utils.exp.userEmailReg.test(em);
},
verifyInputPassword: function verifyInputPassword(pw, pw_re) {
return pw === pw_re;
},
verifyUserNum: function verifyUserNum(num) {
return utils.exp.userNumReg.test(num);
},
verifyUserName: function verifyUserName(name) {
return utils.exp.userNameReg.test(name);
},
verifyUserUnique: function verifyUserUnique(num, callback) {
var xhr = new XMLHttpRequest();
var flag =false;
xhr.open('GET', '/verifyUserUnique?num='+num, true);
var overTimer = utils.common.overTime(4000, '服务器超时', callback);
xhr.onreadystatechange = function () {
if (xhr.readyState==4 && xhr.status==200) {
window.clearTimeout(overTimer);
var res = window.JSON.parse(xhr.responseText);
console.log(res.instance);
if(res.code == '01') {
flag = true;//说明用户不存在,唯一
} else {
flag = false;//说明用户不存在,不唯一
}
typeof(callback) === 'function'?callback(null, flag):callback('typeError', null);
}
};
try {
xhr.send();
} catch (error) {
callback(error);
}
}
}
}

错误传递/API设计/Error类的设计

我们在调试程序中,往往是根据错误提示来进行bug排除的。特别是在自己对代码不熟、或使用了第三方的代码时,如果没有一套设计优良的错误捕捉提示,bug的排除往往非常的低效。

这里就需要我们对代码进行错误捕捉与传递。err形参放在哪里?在哪里抛出错误?如何帮助开发者快速定位bug源头?这些都需要进行设计才行。

当网站整体搭建差不多的时候,我将根据实际需求,参考Express框架中的错误传递机制,设计一套自己的机制,来帮助开发者快速开发。

文章目录
  1. 1. 模型设计
    1. 1.1. 问卷类行为的设计
      1. 1.1.1. 问卷模型
    2. 1.2. 问题模型
    3. 1.3. 注册登录页的行为设计
      1. 1.3.1. 基本功能:
      2. 1.3.2. 方案
    4. 1.4. 错误传递/API设计/Error类的设计