【问题标题】:sails.js access controller method from controller methodsails.js 从控制器方法访问控制器方法
【发布时间】: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 是的,它会起作用,但它不是一回事,所以我无法在该文件之外使用它....

标签: javascript node.js sails.js controllers


【解决方案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);
          ...
        }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-20
        • 2016-03-18
        • 2011-10-22
        • 1970-01-01
        • 2015-06-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多