Page Contents
Page Contents
REVIEW COMMENT from Rand
See issue #800

概要

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();
});

下面的例子, 在任何远程方法执行前被调用:

/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: Express Request object. 

  • ctx.result: Express Response object.

ctx.req.accessToken

用户调用远程方法使用的accessToken 。

ctx.result

对于afterRemote钩子, ctx.result包含了发送给客户端的data。 在发送数据给客户端之前可以修改这个对象。