生成器函数不产生正确的值
Generator function does not yield proper value
我最近学习了一些 ES6,并在 io.js 上使用 koa.js 运行 开始了我的新项目。
在下面的代码中,我试图检查是否已经有另一个具有相同 url slug
的项目。
但是 counter.next().value
的值总是 returns 一个函数,因此函数 _slugExists
总是 returns true
'use strict';
let _ = require('lodash');
let config = require('../../config');
let monk = require('monk');
let wrap = require('co-monk');
let db = monk(config.db);
let _apps = wrap(db.get('apps'));
function _validateApp(app) {
let slug = app.slug.trim();
if (!app.name.trim()) {
throw new Error('App name was not specified.');
}
if (!slug) {
throw new Error('App URL was not specified.');
}
if (_slugExists(slug)) {
throw new Error('Another app with the same URL already exists.');
}
}
function* _count(filter) {
yield _apps.count(filter);
}
function _slugExists(slug) {
let counter = _count({
slug: slug
});
return counter.next().value !== 0;
}
module.exports = {
list: function*(next) {
this.status = 200;
this.body = yield _apps.find({});
},
create: function*(next) {
try {
let app = this.request.body;
_validateApp(app);
this.status = 201;
this.body = {
id: yield _apps.insert({
name: app.name.trim(),
slug: app.slug.trim(),
created_at: new Date()
})
};
} catch (error) {
console.log(`[ERROR] ${error.message}`);
this.status = 500;
this.body = {
error: error.message
};
}
}
}
在基于co的koa中,任何异步操作都必须yield
承诺一直到koa .您还可以 yield
生成器,但不能是迭代器。特别重要的是确保嵌套的异步操作不会被挂起:
function* middleware(next) {
yield Promise.resolve(0); // Yielding a promise. Good.
yield (function() { return Promise.resolve(0); })(); // Also yielding a promise. Good.
yield gen(4); // Yielding iterator. NOT GOOD!
yield gen; // Yielding generator. Good, but no arg.
yield* gen(4); // Delegating iterator. Good!
hangingNested(); // Not yielding anything, async is lost. NOT GOOD!
yield properNested; // Yielding generator with nested delegate, good!
}
function* gen(arg) {
yield Promise.resolve(1);
yield Promise.resolve(2);
yield Promise.resolve(3);
return arg;
}
function hangingNested() { // not a generator, nothing is yielded outside.
gen(4); // iterator is lost.
}
function* properNested() {
yield* gen(4); // Delegating iterator.
}
考虑到这一点,您可以通过多种方式修复代码,例如:
function* _validateApp(app) {
let slug = app.slug.trim();
if (!app.name.trim()) {
throw new Error('App name was not specified.');
}
if (!slug) {
throw new Error('App URL was not specified.');
}
if (yield* _slugExists(slug)) {
throw new Error('Another app with the same URL already exists.');
}
}
function* _count(filter) {
return yield _apps.count(filter);
}
function* _slugExists(slug) {
let counter = yield* _count({
slug: slug
});
return counter !== 0;
}
module.exports = {
list: function*(next) {
this.status = 200;
this.body = yield _apps.find({});
},
create: function*(next) {
try {
let app = this.request.body;
yield* _validateApp(app);
this.status = 201;
this.body = {
id: yield _apps.insert({
name: app.name.trim(),
slug: app.slug.trim(),
created_at: new Date()
})
};
} catch (error) {
console.log(`[ERROR] ${error.message}`);
this.status = 500;
this.body = {
error: error.message
};
}
}
}
我最近学习了一些 ES6,并在 io.js 上使用 koa.js 运行 开始了我的新项目。
在下面的代码中,我试图检查是否已经有另一个具有相同 url slug
的项目。
但是 counter.next().value
的值总是 returns 一个函数,因此函数 _slugExists
总是 returns true
'use strict';
let _ = require('lodash');
let config = require('../../config');
let monk = require('monk');
let wrap = require('co-monk');
let db = monk(config.db);
let _apps = wrap(db.get('apps'));
function _validateApp(app) {
let slug = app.slug.trim();
if (!app.name.trim()) {
throw new Error('App name was not specified.');
}
if (!slug) {
throw new Error('App URL was not specified.');
}
if (_slugExists(slug)) {
throw new Error('Another app with the same URL already exists.');
}
}
function* _count(filter) {
yield _apps.count(filter);
}
function _slugExists(slug) {
let counter = _count({
slug: slug
});
return counter.next().value !== 0;
}
module.exports = {
list: function*(next) {
this.status = 200;
this.body = yield _apps.find({});
},
create: function*(next) {
try {
let app = this.request.body;
_validateApp(app);
this.status = 201;
this.body = {
id: yield _apps.insert({
name: app.name.trim(),
slug: app.slug.trim(),
created_at: new Date()
})
};
} catch (error) {
console.log(`[ERROR] ${error.message}`);
this.status = 500;
this.body = {
error: error.message
};
}
}
}
在基于co的koa中,任何异步操作都必须yield
承诺一直到koa .您还可以 yield
生成器,但不能是迭代器。特别重要的是确保嵌套的异步操作不会被挂起:
function* middleware(next) {
yield Promise.resolve(0); // Yielding a promise. Good.
yield (function() { return Promise.resolve(0); })(); // Also yielding a promise. Good.
yield gen(4); // Yielding iterator. NOT GOOD!
yield gen; // Yielding generator. Good, but no arg.
yield* gen(4); // Delegating iterator. Good!
hangingNested(); // Not yielding anything, async is lost. NOT GOOD!
yield properNested; // Yielding generator with nested delegate, good!
}
function* gen(arg) {
yield Promise.resolve(1);
yield Promise.resolve(2);
yield Promise.resolve(3);
return arg;
}
function hangingNested() { // not a generator, nothing is yielded outside.
gen(4); // iterator is lost.
}
function* properNested() {
yield* gen(4); // Delegating iterator.
}
考虑到这一点,您可以通过多种方式修复代码,例如:
function* _validateApp(app) {
let slug = app.slug.trim();
if (!app.name.trim()) {
throw new Error('App name was not specified.');
}
if (!slug) {
throw new Error('App URL was not specified.');
}
if (yield* _slugExists(slug)) {
throw new Error('Another app with the same URL already exists.');
}
}
function* _count(filter) {
return yield _apps.count(filter);
}
function* _slugExists(slug) {
let counter = yield* _count({
slug: slug
});
return counter !== 0;
}
module.exports = {
list: function*(next) {
this.status = 200;
this.body = yield _apps.find({});
},
create: function*(next) {
try {
let app = this.request.body;
yield* _validateApp(app);
this.status = 201;
this.body = {
id: yield _apps.insert({
name: app.name.trim(),
slug: app.slug.trim(),
created_at: new Date()
})
};
} catch (error) {
console.log(`[ERROR] ${error.message}`);
this.status = 500;
this.body = {
error: error.message
};
}
}
}