Sign up ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

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?

share|improve this question

1 Answer 1

up vote 1 down vote accepted

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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