gdc3000
gdc3000

Reputation: 23

Trouble working sync with async javascript

I'm working in my own rss reader using JS, JQuery and PHP for serving the data as JSON. What I'm doing basically is making async calls to my server to get JSONs with the posts, then on 'success' I parse them using a '$.each' and with JQuery load the content in the DOM. All of this operations were made async, but now I need to call them in a certain order, and when everithin is done THEN calling a function to process the data. To give you some background on my task, what I'm doing is a query over a small list of RSS sources to get just the very latest post. With them I concat a string and this string is passed to a text-to-speech service. I've managed to make it work using an arbitrary setTimeout value of 10 seconds, but my goal is to call the function when all the sources have been processed.

This is a basic version of my parser:

function urgent_posts(url) {
  $.ajax({
    //the location of my server
    url: 'myPostServer.php?url=' + encodeURIComponent(url),
    dataType: 'json',
    success: function(data) {
      //do this for each entry in the feed
      $.each(data.feed.entries, function(key, value) {
        //validate the date to get just the latest post
        if (is_urgent(value.publishedDate)) {
          //if condition is met save the title
          save_urgent_post_title(value.title);
        }
      });
    }
  });
}

What I did to 'make it work' was the following:

$('#test_button').on('click',function(){

  urgent_posts(source_1);
  urgent_posts(source_2);
  urgent_posts(source_3);
  //and so on...
  urgent_posts(source_n);

  setTimeout(function(){
    text_to_speech(get_urgent_post_string);
  },10000);

});

I tried with no result to make use of the deferred object y JQuery like this:

function urgent_posts(url) {
  var deferred = $.Deferred();
  $.ajax({
    //the location of my server
    url: 'myPostServer.php?url=' + encodeURIComponent(url),
    dataType: 'json',
    success: function(data) {
      //do this for each entry in the feed
      $.each(data.feed.entries, function(key, value) {
        //validate the date to get just the latest post
        if (is_urgent(value.publishedDate)) {
          //if condition is met save the title
          save_urgent_post_title(value.title);
        }
      });
    }
  });
  return deferred.promise();
}

And chaining everything together:

$('#test_button').on('click',function(){

  urgent_posts(source_1)
  .then(urgent_posts(source_2))
  .then(urgent_posts(source_3))
  .then(function(){
    text_to_speech(get_urgent_post_string);
  });

});

I'd apreciatte your comments and suggestions.

Upvotes: 0

Views: 70

Answers (2)

gdc3000
gdc3000

Reputation: 23

I manage to solve the problem using this article: link

The refactored code looks like this now:

function urgent_posts_feed_1(callback) {
  return $.ajax({
    //the location of my server
    url: 'myPostServer.php?url=' + encodeURIComponent(feed_1),
    dataType: 'json',
    success: function(data) {
      //do this for each entry in the feed
      $.each(data.feed.entries, function(key, value) {
        //validate the date to get just the latest post
        if (is_urgent(value.publishedDate)) {
          //if condition is met save the title
          save_urgent_post_title(value.title);
        }
      });
    }
  });
}

I repeat myself (I know it's not cool to do so) and write the following functions manually setting the url:

urgent_posts_feed_2 urgent_posts_feed_3 urgent_posts_feed_4 ... urgent_posts_feed_n

And finally...

urgent_post_feed_1()
.then(urgent_post_feed_2)
.then(urgent_post_feed_3)
//...
.then(urgent_post_feed_n)
.then(function(){
    text_to_speech(get_urgent_post_string);
});

This way it works like a charm. Now I have to figure out how to pass parameters to the function and not interfer with the callback.

Upvotes: 0

Magus
Magus

Reputation: 15104

First, your deferred object is never resolved. You have to add the deferred.resolve() somewhere. Just after the $.each loop looks like a nice place.

Second, $.ajax already returns a promise. So you can just write this :

return $.ajax({
    //the location of my server
    url: 'myPostServer.php?url=' + encodeURIComponent(url),
    dataType: 'json',
    success: function(data) {
      //do this for each entry in the feed
      $.each(data.feed.entries, function(key, value) {
        //validate the date to get just the latest post
        if (is_urgent(value.publishedDate)) {
          //if condition is met save the title
          save_urgent_post_title(value.title);
        }
      });
    }
  });

Upvotes: 3

Related Questions