学习nc-example的疑问
发布于 3 年前 作者 Web-Kevin 1930 次浏览 来自 问答

前几天有幸看到@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转

@ncuzp 多谢!

return co(this.render('login', data));

这句语句是否可以直接写成 this.render(‘login’, data)

@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用法

回到顶部