2

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 编译器添加的这些返回语句的任何副作用?正确性和性能明智?

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

4

2 回答 2

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 生成此类数组。

于 2013-09-18T14:39:32.077 回答
1

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 并将控制器方法视为私有的(实现细节)。

于 2013-09-18T14:40:45.180 回答