Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ctx对象上没有mongo方法? #23

Open
varyuanye opened this issue Jan 10, 2017 · 3 comments
Open

ctx对象上没有mongo方法? #23

varyuanye opened this issue Jan 10, 2017 · 3 comments
Labels

Comments

@varyuanye
Copy link

varyuanye commented Jan 10, 2017

  return async function mongo(ctx, next) {
        if (ctx.mongo) return await next();
        Object.assign(ctx, {
            mongo: function(mod, data) {
                if (!Model || !Model[mod]) {
                    debug("can't find model : " + mod);
                    return;
                }
                return (new Model[mod](data));
            },
            mongoMap: function(list) {
                return Promise.all(list.map(mongoExecMap));

                function mongoExecMap(opt) {
                    let arg = opt.arg || [];
                    let model = opt.model;
                    let fun = opt.fun;
                    let execfun = (fun.constructor.name === 'GeneratorFunction') ? co.wrap(fun) : fun;
                    let execRes = execfun.apply(model, arg);
                    return execRes.exec ? execRes.exec() : execRes;
                }
            }
        })
        await next();

我在中间添加了wechat的中间件作用自动拉取access_token,以及自动拉取用户列表数据

  1. 文档中是在controller中使用this调用,我希望在wechat中间件中链接mongo(在每天定点同步关注用户列表)上面这个代码我console.log(ctx.mongo)结果是undefined,如何在中间件中调用mongo
  2. 这个router这个中间件资质愚钝,实在是不太懂,, ctx和this实在是搞不明白.官方文档不是都可以用么但是这里的ctx和this是有区别的,就上面这个mongo的中间件.我看到object.assign已经将mongo合并到ctx上了..但是没什么console ctx还是没有
@xiongwilee
Copy link
Owner

代码debug下看看,确定Obejct.assign这一句执行了吗?

src/app.js里有一个判断,如果你不配置数据库连接,是不会注入这个中间件的:

  // 如果配置了mongo.api则连接数据库
  config.mongo.api[appName] && vapp.use(Middles.mongo(vapp, {
    root: appPath + '/model/mongo',
    connect: config.mongo.api[appName]
  }))

@varyuanye
Copy link
Author

varyuanye commented Jan 11, 2017

module.exports = function graceMongo(app, options) {

    const root = options.root;
    const connect = options.connect;
    // 如果root不存在则直接跳过
    if (!fs.existsSync(root)) {
        debug('error : can\'t find mongo path ' + root);
        return async function mongo(ctx, next) { await next() }
    }

    // 创建数据库连接
    let db = mongoose.createConnection(connect);
    db.on('error', function(err) {
        debug(`error: connect ${connect} ${err}`);
    });
    db.once('open', function() {
        debug(`connect ${connect} success!`);
    });

    let Schema = {},
        Model = {};
    _ls(root).forEach(function(filePath) {
        if (!/.js$/.test(filePath)) {
            return;
        }

        let mod = require(filePath);
        // 创建schema
        let _schema = new mongoose.Schema(mod.schema[0], mod.schema[1]);
        _schema.methods = mod.methods;

        // 发布为Model
        let _model = db.model(mod.model, _schema);
        Schema[mod.model] = _schema;
        Model[mod.model] = _model;
    });
    console.log('数据库链接创建成功')
    console.log('appMongo'+root)
    console.log('数据库链接路径'+connect)

    return async function mongo(ctx, next) {
        if (ctx.mongo) return await next();
        console.log('mongo开始挂载')
        Object.assign(ctx, {
            /**
             * mongo
             * @return {Object} 返回一个Entity对象
             */
            mongo: function(mod, data) {
                if (!Model || !Model[mod]) {
                    debug("can't find model : " + mod);
                    return;
                }
                return (new Model[mod](data));
            },
            /**
             * mongoMap
             * @param {Array} list mongo请求列表
             *        {Object}    list[].model 模型
             *        {Array}     list[].arg 参数
             *        {Function}  list[].fun 模型方法
             */
            mongoMap: function(list) {
                return Promise.all(list.map(mongoExecMap));

                function mongoExecMap(opt) {
                    let arg = opt.arg || [];
                    let model = opt.model;
                    let fun = opt.fun;

                    // 如果fun是generator则转成Promise
                    let execfun = (fun.constructor.name === 'GeneratorFunction') ? co.wrap(fun) : fun;

                    // fun有可能不是Promise, 利用mongoose中的exec()方法转为promise
                    // 参考:http://mongoosejs.com/docs/promises.html
                    let execRes = execfun.apply(model, arg);
                    return execRes.exec ? execRes.exec() : execRes;
                }
            }
        })
        console.log('mongo挂载完成')
        await next();
    };
}

已经在中间console一次数据,结果分别是这样的

数据库链接创建成功
appMongoC:\demo_repository\koa-grace\app\wechat/model/mongo
数据库链接路径mongodb://localhost:12345/wechat
C:\demo_repository\koa-grace\middleware\wechat\token\access_token.json
wechat组件进入页面
数据库链接创建成功
appMongoC:\demo_repository\koa-grace\app\blog/model/mongo
数据库链接路径mongodb://localhost:12345/blog
数据库链接创建成功
appMongoC:\demo_repository\koa-grace\app\blog/model/mongo
数据库链接路径mongodb://localhost:12345/blog
mongo开始挂载
mongo挂载完成
[Function: mongo]

可以看到mongo似乎是成功挂载上了
但是当第二次测试的时候就变成

mongo开始挂载
mongo挂载完成
undefined

挂载失败.但是if (ctx.mongo) return await next();当ctx.mongo是undefined的时候应该是继续挂载到ctx上啊..然而并没有...

@xiongwilee
Copy link
Owner

但是当第二次测试的时候就变成

是说,第一次刷新能在控制器里读到this.mongo方法,第二次刷新就看不到了?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants