REVIEW COMMENT from Rand
See issue #800</div>
概要
LoopBack提供两种类型的钩子:
- Remote钩子, 在远程方法被调用的前后执行。
- Model 钩子, 在模型方法被调用的前后执行。
远程钩子使得你可以在一个远程方法被调用的前后之行一个函数:
beforeRemote()
在远程方法被调用前之行。afterRemote()
在远程方法被调用后之行。
签名
beforeRemote()
和 afterRemote() 有同样的签名;
_modelName_.beforeRemote( _methodName_, function( ctx, _modelInstance_, next) {
...
next();
}
_modelName_
是模型的名字。_methodName_
是远程方法名。可以是一个自定义的远程方法 也可以是一个继承自PersistedModel 的标准CRUD方法。可以包含通配符去匹配多个方法(见下)。ctx
是一个 context object._modelInstance_
是受影响的模型实例。
在methodName中使用星号 '*'匹配任何字符。使用
'*.*' 匹配任意静态方法
; 使用 'prototype.*'匹配任意实例方法。
上面的例子包含一个next()的调用。 你必须在你的钩子回调方法里面调用next()。 你可以不在函数的最后调用next(), 但是你必须调用next(), 不管你是在回调函数的开始、中间、最后调用。
例子
下面的例子定义了一个远程钩子在远程方法count()执行后被调用:
/common/models/model.js
var request = require('request');
Users.afterRemote('count', function(ctx, affectedModelInstance, next) {
request.post({
url: 'http://another.server.com/',
method: 'POST',
json: ctx.result
}, function(err, response) {
if (err) console.error(err);
next();
});
});
下面的例子在方法名中使用了通配符。当任何以”save”结尾的远程方法被调用被执行:
/common/models/model.js
User.beforeRemote('*.save', function(ctx, unused, next) {
if (ctx.req.accessToken) {
next();
} else {
next(new Error('must be logged in to update'))
}
});
User.afterRemote('*.save', function(ctx, user, next) {
console.log('user has been saved', user);
next();
});
Important:
钩子的第二个参数(上面的例子中第二个参数是user)就是ctx.result, 他不总是存在的。
下面的例子, 在任何远程方法执行前被调用:
/common/models/model.js
// ** 匹配prototype.* 和 *.*
User.beforeRemote('**', function(ctx, user, next) {
console.log(ctx.methodString, 'was invoked remotely'); // users.prototype.save was invoked remotely
next();
});
Other wildcard examples
// 在任何静态方法前执行
User.beforeRemote('*', ...);
// 在任何实例方法前执行
User.beforeRemote('prototype.*', ...);
// 防止用户密码被发送给客户端
User.afterRemote('**', function (ctx, user, next) {
if(ctx.result) {
if(Array.isArray(ctx.result)) {
ctx.result.forEach(function (result) {
result.password = undefined;
});
} else {
ctx.result.password = undefined;
}
}
next();
});
Context对象
远程钩子提供了一个上下文对象 ctx
,它包含了transport-specific 数据 (HTTP: req
和 res
). The ctx
object also has a set of consistent APIs across transports.
Applications that use loopback.rest() middleware provide the following additional ctx
properties:
ctx.req.accessToken
用户调用远程方法使用的accessToken
。
Important:
如果远程方法不是被一个登录用户调用,那么ctx.req.accessToken
i为undefined。
ctx.result
对于afterRemote
钩子, ctx.result包含了发送给客户端的data。
在发送数据给客户端之前可以修改这个对象。
Important:
ctx.result的值不总是存在的。