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

How can I pass data between hooks #766

Closed
projectxmaker opened this issue Nov 7, 2014 · 16 comments
Closed

How can I pass data between hooks #766

projectxmaker opened this issue Nov 7, 2014 · 16 comments

Comments

@projectxmaker
Copy link
Contributor

Hi,

I would like to pass data between hooks, but don't know how, if I set it as global variable under module.export in modelName.js, it's not safe between requests.

for example:

  • beforeRemote: I have a variable modelData = A.
  • afterRemote: I would like to use variable modelData at this phase.

thanks for any help :)

@bajtos do you have any idea ^^

@bajtos
Copy link
Member

bajtos commented Nov 7, 2014

Add them to the ctx object.

Customer.beforeRemote('**', function(ctx, unused, next) {
  ctx.modelData = "A";
  next();
});

Customer.afterRemote('**', function(ctx, unused, next) {
  console.log('modelData', ctx.modelData);
});

@bajtos bajtos closed this as completed Nov 7, 2014
@bajtos bajtos added question and removed question labels Nov 7, 2014
@bajtos
Copy link
Member

bajtos commented Nov 7, 2014

See #337 for a more advanced solution that can be used to access context data from any method.

@projectxmaker
Copy link
Contributor Author

👍 cool, thanks for your help

@projectxmaker
Copy link
Contributor Author

@bajtos
another question, I just read #337, but had no luck to find a way to get context object from model instance or even from a model hook (beforeCreate, afterCreate, etc).

module.exports = function(modelName) {
  // I'd like to get the context here, is there any way ?
  var a = modelName.[somehow].ctx.modelData; 

  // or even in model hook ?
  modelName.beforeSave =  function(next, mdl) {
    var a = mdl.[somehow].ctx.modelData;
  }
}

^^

@bajtos
Copy link
Member

bajtos commented Nov 10, 2014

var ctx = loopback.getCurrentContext();

@bajtos
Copy link
Member

bajtos commented Nov 10, 2014

  // I'd like to get the context here, is there any way ?
  var a = modelName.[somehow].ctx.modelData; 

There is no context at the time your model script is run, as the context is created always per incoming request.

  // or even in model hook ?
  modelName.beforeSave =  function(next, mdl) {
    var a = mdl.[somehow].ctx.modelData;
  }

This is where you can call loopback.getCurrentContext().

Keep in mind that loopback.getCurrentContext() is different from the ctx argument passed to beforeRemote and afterRemote hooks.

module.exports = function(Customer) {
  Customer.beforeRemote('**', function(remotingCtx, unused, next) {
    loopbackCtx = loopback.getCurrentContext();
    // save the value from `?someQueryParam=value`
    loopbackCtx.modelData = remotingCtx.req.query.someQueryParam;
    next();
  });

  Customer.beforeSave =  function(next, mdl) {
    loopbackCtx = loopback.getCurrentContext();
    this.contextData = loopbackCtx.modelData; // the value stored above
    next();
  };
};

@projectxmaker
Copy link
Contributor Author

@bajtos thanks for your answer ^^

but I got error when trying to get "loopbackCtx" with "loopback.getCurrentContext()"

module.exports = function(Customer) {
  Customer.beforeRemote('**', function(remotingCtx, unused, next) {
    loopbackCtx = loopback.getCurrentContext();
    // save the value from `?someQueryParam=value`
    loopbackCtx.modelData = remotingCtx.req.query.someQueryParam;
    next();
  });

returned error is about "has no method 'getCurrentContext"

"name": "TypeError",
    "status": 500,
    "message": "Object function createApplication() {\n  var app = express();\n\n  merge(app, proto);\n\n  app.loopback = loopback;\n\n  // Create a new instance of models registry per each app instance\n  app.models = function() {\n    return proto.models.apply(this, arguments);\n  };\n\n  // Create a new instance of datasources registry per each app instance\n  app.datasources = app.dataSources = {};\n\n  // Create a new instance of connector registry per each app instance\n  app.connectors = {};\n\n  // Register built-in connectors. It's important to keep this code\n  // hand-written, so that all require() calls are static\n  // and thus browserify can process them (include connectors in the bundle)\n  app.connector('memory', loopback.Memory);\n  app.connector('remote', loopback.Remote);\n\n  return app;\n} has no method 'getCurrentContext'",
    "details": null

I did something wrong or anything missing ? :(

@bajtos
Copy link
Member

bajtos commented Nov 11, 2014

See the discussion in #775.

You must ensure that loopbak.context middleware was run before you can call loobpack.getCurrentContext. The context middleware is usually called by loopback.rest() for you. If your setup is nonstandard, then you must add the middleware manually yourself.

@bajtos
Copy link
Member

bajtos commented Nov 11, 2014

Actually, the context middleware was not released yet. You have to use loopback from github master to get this new feature:

$ npm install strongloop/loopback

@bluestaralone
Copy link

"Keep in mind that loopback.getCurrentContext() is different from the ctx argument passed to 
beforeRemote and afterRemote hooks.". 

@bajtos
Can you tell me what are different between them ?

And another problem is when i request with accessToken was set: "loobpack.getCurrentContext" return null.

@bajtos
Copy link
Member

bajtos commented Nov 13, 2014

Can you tell me what are different between them ?

They are different objects created at different places, thus they don't share the same properties.

Also you have to use .get(name) and .set(name, value) to work with the data in the loopback context, while the remoting context uses plain properties.

And another problem is when i request with accessToken was set: "loobpack.getCurrentContext" return null.

That happens when loopback.context was not executed yet for the given requests. That has usually two sources:

  • you have loopback.token was added before loopback.context (it should be the other way around)
  • you are calling the method outside of a request, e.g. from a boot script

@bluestaralone
Copy link

@bajtos
I just used your example to test and didn't change anything.
I tested on https://github.com/strongloop/loopback-example-app
Step to create bug like this:

  1. run npm install strongloop/loopback
  2. Copy your code into Customer.js
  3. Add debug codes
  4. Run app
  5. Go to explorer page and make a request GET /Customers
  6. Go to explorer page and Login to get AccessToken
  7. Go to explorer page and set AccessToken to header in Explorer page
  8. Go to explorer page and make a request GET /Customers
  9. Check console log

My code:

var loopback = require('loopback');

module.exports = function(Customer) {

  Customer.beforeRemote('**', function(remotingCtx, unused, next) {
    loopbackCtx = loopback.getCurrentContext();
    console.log("beforeRemote", loopbackCtx);
    loopbackCtx.modelData = 'aaaaaaaaaaaaaaa';
    next();
  });

  Customer.beforeSave =  function(next, customer) {
    loopbackCtx = loopback.getCurrentContext();
    console.log("beforeSave", loopbackCtx);
    next();
  };
};

and my log:

supervisor running without clustering (unsupervised)
Browse your REST API at http://localhost:3000/explorer
Web server listening at: http://localhost:3000/
beforeSave null
beforeSave null
beforeSave null
beforeSave null
beforeRemote { name: 'loopback',
  active: { accessToken: undefined },
  _set: [ null, { accessToken: undefined } ],
  id: 
   { create: [Function],
     flags: 15,
     before: [Function],
     after: [Function],
     error: [Function],
     uid: 1,
     data: null } }
beforeRemote null

@bluestaralone
Copy link

@bajtos

you have loopback.token was added before loopback.context 
(it should be the other way around)

Where can i place both of them ?

@bajtos
Copy link
Member

bajtos commented Nov 13, 2014

@bluestaralone I just used your example to test and didn't change anything.

Please open a new issue to track this problem and repost the steps, the code and the log there.

@bluestaralone
Copy link

ok, thanks

@projectxmaker
Copy link
Contributor Author

@bajtos thanks for your answers, I am currently working with @bluestaralone and we are looking forward to your support on #809 :)

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

No branches or pull requests

3 participants