0

I'm new to this kind of problem in javascript and i can't fix this attempt to wait for an asynchronous call combining Angular promise objects and timeouts.

The function onTimeout seems never execute.

getAsyncContent: function (asyncContentInfos) {

    var deferObj = $q.defer();
    var promiseObj = deferObj.promise;
    asyncContentInfos.promiseObject = promiseObj;
    var blockingGuard = { done: false };

    promiseObj.then(function () {
        blockingGuard.done = true;
    });

    this.wait = function () {
        var executing = false;
        var onTimeout = function () {
            console.log("******************** timeout reached ********************");
            executing = false;
        };

        while (!blockingGuard.done) {
            if (!executing && !blockingGuard.done) {
                executing = true;
                setTimeout(onTimeout, 200);
            }
        } 
    };

    $http.get(asyncContentInfos.URL, { cache: true })
        .then(function (response) {
            asyncContentInfos.responseData = response.data;
            console.log("(getAsyncContent) asyncContentInfos.responseData (segue object)");
            console.log(asyncContentInfos.responseData);
            deferObj.resolve('(getAsyncContent) resolve');
            blockingGuard.done = true;
            return /*deferObj.promise*/ /*response.data*/;
        }, function (errResponse) {
            var err_msg = '(getAsyncContent) ERROR - ' + errResponse;
            deferObj.reject(err_msg);
            console.error(err_msg);
        });

    return {
        wait: this.wait
    }
}

Client code is something like this:

var asyncVocabulary = new AsyncContentInfos(BASE_URL + 'taxonomy_vocabulary.json');
getAsyncContent(asyncVocabulary).wait();

And AsyncContentInfos is:

function AsyncContentInfos(URL) {
    this.URL = URL;
    this.responseData = [];
    this.promiseObject;
    }
rfb
  • 1,107
  • 1
  • 7
  • 14
  • 1
    While the while loop is running, it's impossible for the callbacks to `$http.get` and `setTimeout` to be executed, thus resulting in an infinite loop. **blocking is bad**. – Kevin B May 21 '15 at 18:13
  • An alternative would be to check the difference in time rather than using a setTimeout, but you still won't be able to detect when the http request is done until after the while loop exits. – Kevin B May 21 '15 at 18:16
  • Thank you Kevin. Agreeing on **blocking is bad** :), **really**, how could i solve this kind of problem? – rfb May 21 '15 at 18:19
  • Use promises or callbacks. Hint: you already are. You just need to return the promise rather than your object with wait method, then add a callback to it with .then. See daniel's answer below. – Kevin B May 21 '15 at 18:20
  • This way i'm blocking nothing. – rfb May 21 '15 at 18:21
  • 1
    that's kinda the point, you don't need to block anything. – Kevin B May 21 '15 at 18:23
  • 1
    My guess is you are incorrectly using the result of this http request, leading you to believe you need it to be blocking. – Kevin B May 21 '15 at 18:26
  • ok, in a puristic way i have to wrap all code that i'm trying to block on promise resolution, but it's not that simple. – rfb May 21 '15 at 18:27
  • Yes. that is how asynchronous code in javascript works. you must use callbacks, either directly or through either a promise interface or event interface, but either way, there's callbacks, and you can't effectively access the data out of the callbacks. – Kevin B May 21 '15 at 18:28
  • OK thanks. I ***promise*** i won't search for an hack further – rfb May 21 '15 at 18:30

1 Answers1

2

$http.get returns a promise which will resolve when the call completes. Promises are a way to make asyncronous more clean and straight lined than plain old callbacks.

getAsyncContent: function (asyncContentInfos) {

    return $http.get(asyncContentInfos.URL, { cache: true })
        .then(function (response) {
            return response.data;
        }, function (errResponse) {
            console.error(err_msg);
            throw errResponse;
        });
}

Then using it:

getAsyncContent({...}).then(function(yourDataIsHere) {

});

The nice thing about promises is that they can be easily chained.

getAsyncContent({...})
  .then(function(yourDataIsHere) {
     return anotherAsyncCall(yourDataIsHere);
  })
  .then(function(your2ndDataIsHere) {
  });
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445