1

I guess I don't believe in myself as a good programmer but I found out this method on my own (not suggestion I'm the first one to do it, but I didn't follow a guide) so it must be broken somehow.

$q is mainly a callback kind of service for async reasons, but it served me in another way as well.

I might have multiple calls to a long running service, but I only need a response once. So I want to disregard all calls except from the first one and cache the result from that and return to everybody.

If I give everybody a promise when called they get the result when the promise is resolved, even if it was resolved before the promise was actually given, that's a nice feature.

So I could only make the dervice call the first time I give the promise.

myApp.factory('serviceWithLongCall', function ($q, $timeout) {

    var data = {}
    var hasStarted = false;
    var deferred = $q.defer();

    return {
        call: call
    };

    function call() {
        if (!hasStarted) {
            hasStarted = true;
            console.log('timeout started');
            $timeout(function () {
                console.log('timeout ended');
                data = 42;
                deferred.resolve(data);
            }, 3000);
        }

        return deferred.promise;
    }

});

fiddle with example, click some buttons and wait for 3 seconds from first click, later clicks will happen instantly.

Is something off with this method, will I have a race condition?

1

Returning the same promise from a call multiple times for caching reasons is absolutely fine. No race condition that I can think of, and I've used that technique with no issue.

The only small issue with you code is that's it's unnecessary to create the deferred object. $timeout returns a promise that can resolve to the value you want.

myApp.factory('serviceWithLongCall', function ($timeout) {

    var data = {}
    var promise = null;

    return {
        call: call
    };

    function call() {
        if (!promise) {
            console.log('timeout started');
            promise = $timeout(function () {
                console.log('timeout ended');
                data = 42;
                return data;
            }, 3000);
        }

        return promise;
    }
});

Admittedly your use of $timeout might be just for example reasons, but I suspect you can do the same thing with $http.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.