2

我有一项服务可以做一些困难的事情并返回一个承诺:

.factory('myService', function($q) {

    return {
        doSomethingHard: function() {
            var deferred = $q.defer();

            setTimeout(function() {
                deferred.resolve("I'm done!");
            }, 1000);

            return deferred.promise;
        }
    };
})

我有一个控制器,它使用该服务将功能添加到范围:

.controller('MyCtrl', function($scope, myService) {

    $scope.doSomething = function() {
        var promise = myService.doSomethingHard();

        promise.then(function(result) {
            alert(result);
        });
    };

})

我使用指令通过解析属性来调用该控制器函数:

.directive('myDirective', function($parse) {
    return {
        link: function(scope, el, attr) {

            var myParsedFunction = $parse(attr.myDirective);

            el.bind('click', function() {
                myParsedFunction(scope);
            });
        }
    };
})

与模板

<div ng-controller="MyCtrl">
    <button my-directive="doSomething()">The Button</button>
</div>

单击按钮触发事件监听器,它调用控制器函数doSomething,调用服务函数doSomethingHard,返回一个承诺,即永远不会解决

整个事情都在这里:

http://jsfiddle.net/nicholasstephan/RgKaT/

是什么赋予了?

谢谢。

编辑:多亏了 Maksym H.,看起来将 promise resolve 包装在$scope.$apply()其中使其在控制器中触发。我有一个工作小提琴http://jsfiddle.net/RgKaT/4/。但我真的很想把范围排除在我的服务之外。

我也很想知道为什么会这样。或者更好的是,为什么它在包裹在范围内时如果不解决承诺就不起作用。当考虑属性的变化需要消化时,整个 Angular 世界与常规 Javascript 世界的类比是有意义的,但这是一个承诺……带有回调函数。$q 是否只是将承诺标记为已解决并等待范围消化该属性更新并触发其已解决的处理程序函数?

4

2 回答 2

2

这是另一种方式:尝试在指令中定义范围并将此属性绑定到期望父范围。

.directive('myDirective', function() {
  return {
    scope: { myDirective: "=" }, // or { myParsedFunction: "=myDirective" },
    link: function(scope, el, attr) {

        el.bind('click', function() {
            scope.myDirecive(scope); // or scope.myParsedFunction(scope)
        });
    }
  };
})

但主要是在一段时间后解决它时运行摘要:

.factory('myService', function($q, $timeout) {

    return {
        doSomethingHard: function() {
            alert('3. doing something hard');

            var deferred = $q.defer();

            // using $timeout as it's working better with promises
            $timeout(function() {
                alert('4. resolving deferred');
                deferred.resolve('Hello World!'); // Here...
            }, 1000);

            return deferred.promise;
        }
    };
})

jsFiddle

PS确保您将方法作为父范围的模型传递,而不是通过HTML中的“()”应用它

<button my-directive="doSomething">Button</button>

于 2013-04-21T21:22:26.457 回答
1

只需替换setTimeout$timeout(并记住注入$timeout您的服务)。这是一个更新的 jsFiddle

于 2013-05-10T18:35:07.423 回答