sails.js 从控制器方法访问控制器方法

Posted

技术标签:

【中文标题】sails.js 从控制器方法访问控制器方法【英文标题】:sails.js access controller method from controller method 【发布时间】:2014-01-11 04:34:06 【问题描述】:

为什么你不能从另一个控制器中访问其他控制器方法?

像这样。

module.exports = 

   findStore: ->
       # do somthing

   index: ->
      @findStore(); # Error: undefined

编译

module.exports = 
  findStore: function() ,
  index: function() 
    return this.findStore(); // Error: undefined
  
;

如果你不能做到这一点,那为什么不呢?我应该怎么做...

【问题讨论】:

你试过findStore()this.findStore()吗? 是的,@findStore() 就是这样。我刚刚尝试过findStore();...没有运气。 14 年后,您的问题的确切答案是因为您使用this 的位置超出了您的预期范围。如果你已经完成了var fs=findstore: function(),然后从index:function 中调用了fs,它应该可以工作。 . .我认为... 实用的、真实的世界 答案是来自@nidheeshdas @monsto 是的,它会起作用,但它不是一回事,所以我无法在该文件之外使用它.... 【参考方案1】:

过去几个小时遇到同样的问题。我使用了 api/services 文件夹。 它可能不是您所需要的,但它是一种选择。 一个很好的解释是here。 What services would one add to the api/services folder in sails.js

【讨论】:

您可以在我的回答中看到一个示例【参考方案2】:

您可以使用sails.controllers.yourControllerName.findStore()

sails 全局对象引用了几乎所有内容。

【讨论】:

请注意,RabbitController 将被引用为 sails.controllers.rabbit.feed() 很棒的解决方案,对我来说效果很好,注意它区分大小写,IE Rabbit 不起作用,rabbit 可以。 另外值得注意的是,您可以通过sails.middleware.blueprints.create(req, res)调用蓝图操作 还要注意,如果你有一个嵌套的控制器结构(例如控制器 -> v2 -> RabbitController.js),使用sails.controllers.rabbit.feed() 或sails.controllers.v2.rabbit。 feed() 不起作用。我不得不使用@lloop 建议的服务【参考方案3】:

当您只是想快速构建一些东西时,这有点烦人,但从长远来看,它会强制执行良好的代码组织实践(通过将所有业务逻辑推入控制器变得更加困难)。

【讨论】:

那不就是业务逻辑应该驻留的地方吗? 是的,但是对于大型项目,您不希望将控制器的所有业务逻辑代码放在一个文件中 是的,绝对不在一个文件中。 我一直将业务逻辑封装在自定义模块中(通常在服务中)......并根据需要要求它们。【参考方案4】:

至少对我和我的团队而言,在 Sails 中组织代码的最佳方法之一是在服务 (/api/services) 中拥有所有真正的业务逻辑。可以从任何控制器全局访问这些对象。

此外,一个好的做法是在服务中使用 Promise(因为 Sails 在模型方法中使用它们)

只需使用您的代码创建一个商店服务 (StoreService.js):

module.exports = 
  findStore: function(storeId) 
    // here you call your models, add object security validation, etc...
    return Store.findOne(storeId);
  
;

您的控制器应处理与请求、调用服务和返回适当响应相关的所有事情。

例如,在你的例子中,控制器可能有这个:

module.exports = 
  index: function(req, res) 
    if(req.param('id')) 
      StoreService.findStore(req.param('id'))
        .then(res.ok)
        .catch(res.serverError);
     else 
      res.badRequest('Missing Store id');
    
  ,
  findStore: function(req, res) 
    if(req.param('id')) 
      StoreService.findStore(req.param('id'))
        .then(res.ok)
        .catch(res.serverError);
     else 
      res.badRequest('Missing Store id');
    
  ,
;

这样,您就拥有非常简单的控制器,并且所有业务逻辑都由服务管理。

【讨论】:

这里最受欢迎的帖子从字面上回答了这个问题,但这里的这篇帖子是一个实际的解决方案……它着眼于未来的组织来回答这个问题。这是这里存在的真正微妙的 XY 问题的 X 解决方案。 我分享的代码现在应该转换为async/await,但它仍然是相关的。【参考方案5】:

解决这个问题的更优雅的方法是在函数名前使用关键字this

例子:

one: function() 
   console.log('First Function');
,

two: function() 
   // call the function one in the same controller
   this.one();

【讨论】:

【参考方案6】:

我想提出一个可行的解决方案,但不是最好的方法。我们可以使用 bind 函数将上下文与调用源绑定,如下所示:

generateUrl 存在于控制器 A 中

function generateUrl()
  return 'www.google.com';

获取 URL 是控制器 A 中的另一种方法

getURL()
  A.generateURL.bind(A.generateURL) //func call with optional arg

我希望这会有所帮助!

【讨论】:

【参考方案7】:

你可以这样做:

//ArticleController
module.exports = 
  findStore: async () => 
    return await findStoreFunc(req.param('id'));
  ,
  index: async () => 
    ...
    return await findStoreFunc(id);
  
;

const findStoreFunc = async (id) => ...

并使用另一个控制器的功能:

const ArticleController = require('./ArticleController');
//CustomerController
module.exports = 
  index: async () => 
    ...
    let article = await ArticleController.findStore(id);
    ...
  
;

【讨论】:

以上是关于sails.js 从控制器方法访问控制器方法的主要内容,如果未能解决你的问题,请参考以下文章

Sails.js 控制器等待异步服务方法

Sails js渲染局部视图

Sails.js 将数据从部分控制器发送到部分视图

从 Sails.js 中的关联模型访问模型的属性

Sails.js 控制器从 Promise 中获取数据

在 Sails.js 后端项目中访问上传的图像