学习nc-example的疑问
前几天有幸看到@ncuzp https://cnodejs.org/topic/571435ea434cfcfa52684b2b 这篇帖子,有几个疑问想请教一下
'use strict';
let config = require('../config');
let co = require('co');
let md5 = require('md5');
let User = require('../models').User;
// 显示登录界面
exports.showLogin = function* (){
let data = {
config,
user: this.session.user
};
if(data.user){
yield Promise.resolve()
.then(() => this.redirect('/'));
}else{
yield this.render('login', data);
}
};
// 登录提交
exports.login = function* (){
let data = {config};
let req = this.request.body;
let loginname = req.loginname;
let password = md5(req.password);
yield Promise.resolve()
.then(() => User.findOne({loginname: loginname}))
.then((user) => {
if(user && (password === user.password)){
this.session.loginname = loginname;
this.redirect('/');
}else{
data.errMsg = 'please check name & password';
return co(this.render('login', data));
}
});
};
// 显示注册页面
exports.showRegistry = function* (){
if(this.session.user){
this.redirect('/');
}
yield this.render('registry', {config});
};
// 用户注册
exports.registry = function* (){
let data = {config};
let req = this.request.body;
let uname = req.username;
let loginname = req.loginname;
let email = req.email;
let signature = req.signature;
let pass = md5(req.password);
let user = new User();
user.name = uname;
user.loginname = loginname;
user.password = pass;
user.email = email;
user.signature = signature;
// add session
this.session.loginname = loginname;
data.user = user;
yield Promise.resolve()
.then(() => user.save())
.then(() => this.redirect('/'));
};
// 退出登录
exports.logout = function* (){
this.session.user = undefined;
this.session.loginname = undefined;
this.redirect('/');
};
// 查看用户个人信息
exports.userInfo = function* (){
let loginname = this.params.loginname;
let data = {
config,
user: this.session.user
};
yield Promise.resolve()
.then(() => User.findOne({loginname: loginname}))
.then((user) => {data.userintro = user;})
.then(() => co(this.render('user', data)))
};
不理解为何exports.userInfo user 作为参数那值从何而来,还有为何最后用co来渲染,而exports.showLogin的不用 为何有时用return 有时不用 小弟刚接触koa,望大神指点一下 多谢了
5 回复
@Web-Kevin Hi, 这里主要需要理解下Promise的用法以及yield 的用法,
- 第一个问题: exports.userInfo的user值是上面User.findOne的结果
- 第二个问题: 用co是因为那是一个Promise链, 而this.render返回的是一个generator函数, 所以需要用co转成Promise来执行
- 第三个问题: yield是可以直接接一个generator的所以不用co转
@Web-Kevin 这个是不可以的, 这样写应该不会执行, 因为这个是generator的机制, 必须执行next才能使得这个generator执行, 而co的作用说白了就是执行下next将这个generator执行以下然后包装成Promise返回, co的简化模型如下: 例子非常粗浅仅供参考,如果需要还是去看co实现吧:
var g = function *(){}
var co = () => {
return new Promise((resolve, reject) => {
resolve(g.next())
});
}
@ncuzp 真的不好意思,还有最后一个问题
//1
exports.login = function* (){
let data = {config};
let req = this.request.body;
let loginname = req.loginname;
let password = md5(req.password);
yield Promise.resolve()
.then(() => User.findOne({loginname: loginname}))
.then((user) => {
if(user && (password === user.password)){
this.session.loginname = loginname;
this.redirect('/');
}else{
data.errMsg = 'please check name & password';
return co(this.render('login', data));
}
});
};
//2
exports.userInfo = function* (){
let loginname = this.params.loginname;
let data = {
config,
user: this.session.user
};
yield Promise.resolve()
.then(() => User.findOne({loginname: loginname}))
.then((user) => {data.userintro = user;})
.then(() => co(this.render('user', data)))
};
第一段代码使用return,而第二段使用then来进行渲染也不需要return,那是不是第二段代码可以这么写?
exports.userInfo = function* (){
let loginname = this.params.loginname;
let data = {
config,
user: this.session.user
};
yield Promise.resolve()
.then(() => User.findOne({loginname: loginname}))
.then((user) => {data.userintro = user;
return co(this.render('user', data))})
};
@Web-Kevin 对的,可以这么写, 这是Promise用法