Mongoose方法返回undefined

时间:2017-07-10 14:26:33

标签: javascript node.js mongodb express mongoose

我已成功定义并使用我的项目mongoose模型:

const Schema = mongoose.Schema;

const Item = new Schema({
  name    : String,
  hierarchy: [{ type: Schema.ObjectId, ref: this }],
  hierarchy_size: Number
});

在保存前后,我将hierarchy_size和层次结构值相应地填充到它的属性中,使其成为分层树:

Item.pre("save", function(next) {
    this['hierarchy_size'] = this.hierarchy.length;
    next();
})

Item.post('save', (doc, next) => {
    if ((doc._id) && (doc.hierarchy.length == 0)) {
        doc.hierarchy = [doc._id];
        doc.save();
    }
    next();
})

现在我正在为每个根子进行运行(在查询hierarchy_size == 1之后),以下方法为getChildren:

Item.methods.getChildren = function() {
    this.model("Item").find({hierarchy: this._id, hierarchy_size: this.hierarchy_size+1}).exec(function(err, children){
        if(!err){
            let childrenHierarchy = [];
            for(let child of children){
                childrenHierarchy.push(child);
            }
            return childrenHierarchy;
        }
    })
};

但是在控制器上,当迭代第一级实例时,我对item.getChildren()的调用返回undefined。

app.get('/items', (req, res) => {
    Item.find({hierarchy_size: 1}).exec((err, menus) => {
      if (err) {
        res.status(500).json(err.message);
      } else {
        let rootTree = []
        for(let item of items){
          rootTree.push(item.getChildren());
        }
        res.status(200).json(rootTree);
      }
    });
});

调用item.getChildren方法,在方法内部的console.log(this)显示正确的实例数据,使用正确的子对象填充childrenHierarchy,但返回undefined而不是childrenHierarchy内容。有关它为何发生的任何提示?我是否正常使用第一个查询返回的实例?

2 个答案:

答案 0 :(得分:1)

这是不可能的,因为你无法从同步方法中的异步调用返回。

你可以做的是,你可以为你的方法传递一个回调函数,如下所示:

Item.methods.getChildren = function(callback) {
    this.model("Item").find({hierarchy: this._id, hierarchy_size: this.hierarchy_size+1}).exec(function(err, children){
        if(!err){
            let childrenHierarchy = [];
            for(let child of children){
                childrenHierarchy.push(child);
            }
            callback(childrenHierarchy);
        }
    })
};

或者你可以使用承诺,让你的生活更轻松......

答案 1 :(得分:1)

首先,我强烈建议你改用Promise,以避免回调噩梦。

答案很简单:你使用async函数和普通对象一样,第二个,你没有使用getChildren方法返回任何东西。

为了解决您的问题,请将getChildren修改为:

Item.methods.getChildren = function() {
    return this.model("Item").find({hierarchy: this._id, hierarchy_size: this.hierarchy_size+1})
    .exec()
    .then(result => {
        let childrenHierarchy = [];
            for(let child of children){
                childrenHierarchy.push(child);
            }
            return childrenHierarchy;
    })
    .catch(err => {
        console.log("the error occured!", err)
    })
};

但是,您还需要修改API端点:

app.get('/items', (req, res) => {
    Item.find({ hierarchy_size: 1 })
        .exec()
        .then(menus => {
            let rootTree = []
            let promiseChain = Promise.resolve({});

            for (let item of menus) {
                promiseChain = promiseChain.then(() => {
                    return item.getChildren()
                    .then(children => {
                        rootTree.push(children);
                    })
                })
            }
            promiseChain.then(() => {
                res.status(200).json(rootTree);
            })  
        })
        .catch(err => {
            res.status(500).json(err.message);
        })   
});