2015-10-12 7 views
0

Я недавно узнал немного ES6 и начал свой новый проект, используя koa.js, запущенный на io.js.Функция генератора не дает правильного значения

Уверен, что здесь что-то не хватает, но вам нужна ваша помощь в этом. В приведенном ниже коде я пытаюсь проверить, есть ли еще один элемент с тем же url slug.

Но значение counter.next().value всегда возвращает функцию и, следовательно, функция _slugExists всегда возвращает 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 
     }; 
    } 
    } 
} 
+2

Почему Вы используете генератор здесь вообще? Что вы получаете, если не используете генератор? Что означает '_apps.count', должен возвращаться в любом случае? –

ответ

1

В КоА, которая основана на совместно любая операция асинхронной должны yield обещания вплоть до коа. Вы можете также генераторы 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 
     }; 
    } 
    } 
}