AngularJS范围和延期

时间:2013-04-21 21:01:06

标签: angularjs angularjs-directive promise angularjs-scope

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

.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.,看起来好像在$scope.$apply()中包含promise promise会让它在控制器中激活。我有一个工作小提琴http://jsfiddle.net/RgKaT/4/。但我真的想保留我的服务范围。

我也很想知道为什么会这样。或者更好的是,为什么它在没有解决承诺的情况下无法工作,同时包含在范围内。整个Angular世界与常规Javascript世界类比在考虑属性时是有意义的,因为需要消化变化,但这是一个承诺......具有回调函数。 $ q是否仅将promise更新为已解决并等待范围消化该属性更新并触发其已解析的处理函数?

2 个答案:

答案 0 :(得分:2)

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

.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

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

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

答案 1 :(得分:1)

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