0

I'm trying to use angular promise using $q that is wrapped in 'service' and call it from my controller. Here is the code:

var myController = function ($scope, myService) {
    $scope.doSomething = function (c, $event) {
        $event.preventDefault();
        myService.method1(c).then(function (rslt) {
            alert(rslt);
        }, function (err) {
            alert(err);
        }).then(function () {
            //clean up
        });        
    };
};
var myApp = angular.module('myApp', [])
    .factory('myService', function($q) {
        function _method1(c) {
            var dfr = $q.defer();

            var dt = { sc: c };
            $.ajax({
                type: "POST",
                url: "mypage.aspx/mymethod",
                data: JSON.stringify(dt),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function () {
                    dfr.resolve('actions sucess');
                },
                error: function (msg) {
                    dfr.reject(msg);
                }
            });
            return dfr.promise;
        }
        return { method1: _method1 };
    }).controller('myController', myController);

The problem is that ' alert(rslt);' piece of code is never executed. Service is called and data is updated but first 'then' function is not reached on first click.

What am I doing wrong? Any help appreciated.

0

2 Answers 2

3

I would recoomend you to use $http and $resource instead of $.ajax

Heres an example of $http

myApp.factory('MyService',
[
    '$http',
    '$q',
    '$resource',
function (
    $http,
    $q,
    $resource
) {
    return {
        doSomething : function (somedata) {
            var deferred = $q.defer();

            $http({ method: 'POST', url: '"mypage.aspx/mymethod"', data: somedata }).
                success(function (data, status, headers, config) {
                    deferred.resolve(true);
                }).
                error(function (data, status, headers, config) {
                    deferred.resolve(false);
                });
            return deferred.promise;
        }
    };
}]);
Sign up to request clarification or add additional context in comments.

1 Comment

can you expand on $resource ?
2

Just add the dependency to $rootScope and call $rootScope.$apply() in both callbacks from $.ajax():

success: function () {
    dfr.resolve('actions sucess');
    $rootScope.$apply();
}, ...

But better yet, use Angular's $http service.

5 Comments

I don't understand why triggering the digest cycle solves this example. When you resolve() the promise (return of method1(c), same reference), the then() function should trigger even without an $apply. Only thing I found in the docs is: "$q is integrated with the ng.$rootScope.Scope model observation mechanism ... which means faster propagation ...".
The integration of Angular's $q with Angular means it requires a digest cycle to trigger changes.
Interesting, this is new to me. Do you have a link to this piece of doc?
I haven't found it in the docs, but (surprize!) the code. See e.g. line 213 in the resolve() function, it calls nextTick() to run the callbacks. Angular's nextTick() is bound to the digest cycle (and the reason for this behaviour).
Lol just found the same! Cool stuff. This explains it but sadly the docs are incomplete - worse - In my opinion misleading. Thank you for explaining m8. Valuable background info. Every angular freak should look at their framework code in detail.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.