In Node.js project build with LoopbackJS I need to store data during request.
So I used domain feature:
// pre-processing middleware
app.use(function (req, res, next) {
// create per request domain instance
var domain = require('domain').create();
// save request and response to domain, to make it accessible everywhere
domain.req = req;
domain.res = res;
domain.run(next);
});
Later in required module:
Model.beforeRemote('**', function(oContext, oModel, next) {
// Save method name for later use
process.domain.remoteContext = { /* Here is an error thrown */
methodName: oContext.method.name
};
...
process.domain.res.send() // example of usage
})
BUT when I make request from Safari or IE, process.domain is sometimes undefined! Requesting from Chrome or Firefox works as expected. Any suggestions?
Error response:
{"error":{"name":"TypeError","status":500,"message":"Cannot set property 'remoteContext' of undefined","stack":"TypeError: Cannot set property 'remoteContext' of undefined\n at module.exports (/Users/igormatyushkin/projects/Yash/server/hooks/admin-remote.js:12:34)\n at Function.Model.setup.ModelCtor.beforeRemote.args (/Users/igormatyushkin/projects/Yash/node_modules/loopback/lib/model.js:184:9)\n at execStack (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:363:13)\n at RemoteObjects.execHooks (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:372:10)\n at RemoteObjects.invokeMethodInContext (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:512:8)\n at async.series.results (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/node_modules/async/lib/async.js:610:21)\n at _asyncMap (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/node_modules/async/lib/async.js:249:17)\n at async.eachSeries.iterate (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/node_modules/async/lib/async.js:149:13)\n at async.eachSeries (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/node_modules/async/lib/async.js:165:9)\n at _asyncMap (/Users/igormatyushkin/projects/Yash/node_modules/loopback/node_modules/strong-remoting/node_modules/async/lib/async.js:248:13)"}}
Just found out, that explisity binding req and res to domain at creation moment, solves undefined domains down in execution stack.
app.use(function (req, res, next) {
// create per request domain instance
domain.create().run(function() {
// explicit binding
process.domain.add(req)
process.domain.add(res)
// save request to domain, to make it accessible everywhere
process.domain.req = req;
process.domain.res = res;
next()
});
});
Don't know why this happens, so I leave question open for other possible advices.
It is worth mentioning that domains are not meant to be used to handle errors in this manner. Domains are instead meant to be used to allow modules of an entire application to crash safely (for example, maybe you want to run 3rd party code in a sandbox). A domain is not necessary here (though you are, of course, free to use one)
Furthermore, process.domain
is only set if the given function is executing from within the domain stack. You do not provide information about the Model's call site, so I can only assume that your model is being called from outside of this stack, which is causing the error.
Given that you're hooking to beforeRemote
, which executes before a remote action is executed, I'm going to assume that is being called from outside of the domain stack, and thus process.domain
being undefined is expected behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With