2014-12-03 6 views
0

Я использую [email protected] Я хотел бы изменить категорию сообщения на древовидную структуру. Ниже код работает хорошо, за исключением, когда я создаю категорию, он идет в тупик:Mongoose pre.save() async middleware не работает над созданием записи

var keystone = require('keystone'), 
 
\t Types = keystone.Field.Types; 
 

 
/** 
 
* PostCategory Model 
 
* ================== 
 
*/ 
 

 
var PostCategory = new keystone.List('PostCategory', { 
 
\t autokey: { from: 'name', path: 'key', unique: true } 
 
}); 
 

 
PostCategory.add({ 
 
\t name: { type: String, required: true }, 
 
\t parent: { type: Types.Relationship, ref: 'PostCategory' }, 
 
\t parentTree: { type: Types.Relationship, ref: 'PostCategory', many: true } 
 
}); 
 

 
PostCategory.relationship({ ref: 'Post', path: 'categories' }); 
 

 
PostCategory.scanTree = function(item, obj, done) { 
 
\t if(item.parent){ 
 
\t \t PostCategory.model.find().where('_id', item.parent).exec(function(err, cats) { 
 
\t \t \t if(cats.length){ 
 
\t \t \t \t obj.parentTree.push(cats[0]); 
 
\t \t \t \t PostCategory.scanTree(cats[0], obj, done); 
 
\t \t \t } 
 
\t \t }); 
 
\t }else{ 
 
\t \t done(); 
 
\t } 
 
} 
 

 
PostCategory.schema.pre('save', true, function (next, done) { //Parallel middleware, waiting done to be call 
 
\t if (this.isModified('parent')) { 
 
     this.parentTree = []; 
 
\t \t if(this.parent != null){ 
 
\t \t \t this.parentTree.push(this.parent); 
 
\t \t \t PostCategory.scanTree(this, this, done); 
 
\t \t }else 
 
\t \t \t process.nextTick(done); 
 
    }else 
 
\t \t process.nextTick(done); //here is deadlock. 
 

 
    next(); 
 
}); 
 

 
PostCategory.defaultColumns = 'name, parentTree'; 
 
PostCategory.register();

Спасибо так много.

ответ

0

Я думаю, что это ошибка keystone.js. Я изменил schemaPlugins.js 104 линию

из

this.schema.pre('save', function(next) { 

в

this.schema.pre('save', true, function(next, done) { 

и изменения от линии 124 к следующему,

\t \t // if has a value and is unmodified or fixed, don't update it 
 
\t \t if ((!modified || autokey.fixed) && this.get(autokey.path)) { 
 
\t \t \t process.nextTick(done); 
 
\t \t \t return next(); 
 
\t \t } 
 

 
\t \t var newKey = utils.slug(values.join(' ')) || this.id; 
 

 
\t \t if (autokey.unique) { 
 
\t \t \t r = getUniqueKey(this, newKey, done); 
 
\t \t \t next(); 
 
\t \t \t return r; 
 
\t \t } else { 
 
\t \t \t this.set(autokey.path, newKey); 
 
\t \t \t process.nextTick(done); 
 
\t \t \t return next(); 
 
\t \t }

Это работает.

1

Как я уже объяснял по этому вопросу вы вошли в систему Keystone здесь: https://github.com/keystonejs/keystone/issues/759

Это, как представляется, воспроизводимый ошибка в мангуста, что предотвращает промежуточное программное обеспечение от решения, если:

  • Параллельные трассы промежуточного слоя, который выполняет запрос , а затем
  • серийных промежуточных программные трасс выполняют запрос

Изменения Keystone-х autokey промежуточное программное обеспечение для запуска в параллельном режиме может привести к ошибкам в других случаях использования, поэтому это невозможно. Ответ заключается в том, чтобы реализовать промежуточное ПО parentTree в последовательном режиме вместо параллельного режима.

Кроме того, некоторые другие вещи, которые я заметил:

  • Существует ошибка в ПО промежуточного слоя, где первый родитель добавляется в массив в два раза.
  • Метод scanTree будет лучше реализован в качестве метода на Шэма
  • Вы можете использовать метод findById для более простого родительского запроса

Метод схема выглядит следующим образом:

PostCategory.schema.methods.addParents = function(target, done) { 
    if (this.parent) { 
     PostCategory.model.findById(this.parent, function(err, parent) { 
      if (parent) { 
       target.parentTree.push(parent.id); 
       parent.addParents(target, done); 
      } 
     }); 
    } else { 
     done(); 
    } 
} 

И фиксированное промежуточное ПО выглядит следующим образом:

PostCategory.schema.pre('save', function(done) { 
    if (this.isModified('parent')) { 
     this.parentTree = []; 
     if (this.parent != null) { 
      PostCategory.scanTree(this, this, done); 
     } else { 
      process.nextTick(done); 
     } 
    } else { 
     process.nextTick(done); 
    } 
});