【问题标题】:Implicit returns in Coffeescript and AngularJSCoffeescript 和 AngularJS 中的隐式返回
【发布时间】:2013-09-18 22:40:45
【问题描述】:

Coffeescript 中的以下虚拟控制器:

GlobalTimelineController = ($scope, $http) ->
  $http.get('/api/globalTimeline').success (posts) ->
    $scope.posts = posts

如下编译成Javascript:

(function() {
  var GlobalTimelineController;

  GlobalTimelineController = function($scope, $http) {
    return $http.get('/api/globalTimeline').success(function(posts) {
      return $scope.posts = posts;
    });
  };

}).call(this);

我想知道 Coffee 编译器添加的这些 return 语句有什么副作用吗?正确性和性能明智?

我应该关心这个并在我的方法和回调结束时为空返回吗?

【问题讨论】:

    标签: angularjs coffeescript


    【解决方案1】:

    $http.get 调用返回一个所谓的“promise”,其工作原理如下:

    promise.success = function(fn) {
      promise.then(function(response) {
        fn(response.data, response.status, response.headers, config);
      });
      return promise;
    };
    

    取自 AngularJS 源代码 (/src/ng/http.js:700)

    这意味着无论你的函数返回什么都将被忽略,因此如果它是对象,那么在你的函数完成后对它的引用就会丢失。 因此,从正确性的角度来看,这并不重要。

    现在,如果我们看一下性能,在这种情况下,差异(如果有的话)可以忽略不计。 但是,您始终需要牢记这种行为。如果您在函数中执行的最后一件事是执行具有多次迭代的循环,coffeescript 将返回一个包含每个数组迭代结果的大数组(数组理解)。不仅会影响性能,极端情况下还可能导致JS内存不足!

    您还可以在末尾附加一个 return 语句以防止 coffeescript 生成此类数组。

    【讨论】:

      【解决方案2】:

      TLDR;如果不认为你应该担心这个。

      很久以前解决的唯一问题与单元测试控制器方法有关。

      假设在你的单元测试中你有这样的东西:

        beforeEach inject ($injector)->
          $controller       = $injector.get '$controller'
          injectables   = { ... }
          ctrl = $controller 'app.controllers.FooBarCtrl', injectables
      
      
        describe 'Controller ...', ->
          it 'should have foo property', ->
            expect(ctrl.foo).toBeDefined()
      

      你的控制器看起来像这样:

      name = 'app.controllers.FooBarCtrl'
      angular.module(name, []).controller(name, [
      
        '$scope'
        '$http'
      
        ($scope)->
          scope.foo = 'bar'
          $http.get '/foo/bar', (res)-> console.log 'response: ', res
      
      ])
      

      在这种情况下,您将无法测试任何控制器方法,因为返回的实际上是一个承诺。为了访问实际的控制器方法,您需要返回它,如下所示:

      name = 'app.controllers.FooBarCtrl'
      angular.module(name, []).controller(name, [
      
        '$scope'
        '$http'
      
        ($scope)->
          scope.foo = 'bar'
          $http.get '/foo/bar', (res)-> console.log 'response: ', res
      
          @ # <--- look ma, I'm here!
      ])
      

      但是,我认为这些示例从实际的角度来看并不是很相关,因为在单元测试角度控制器时,您实际上应该处理 $scope 提供的 API,并将控制器方法视为私有的(实现细节)。

      【讨论】:

      • 感谢 Rafal,这对单元测试很有帮助。但我会选择 catvir 的答案,因为它提供了有关返回值和可能的性能问题的更多详细信息。
      • 干杯,np,我不想在这里重复其他答案。
      猜你喜欢
      • 2015-05-18
      • 2013-11-10
      • 2015-03-24
      • 2014-02-27
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 2010-11-07
      相关资源
      最近更新 更多