0

Strange fetch behavior

I'm incurring in a strange problem with fetching XML datas from a network. The problem is this.
I'm parsing a xml file that contains a list of items, with every items being the url of another xml where i need to get the datas. After fetching the list of url and putting that in an array i use a cycle for to scan this array and for every item i send another fetch request for parsing them and getting the datas. After the cycle i populate a grid with the datas and update the view. Here's the behavior i can't seem to understand. The fetch requests inside the for don't get fired till the updateview has been called, basically they are stopped till the original function who called them has finished, basically not populating the array of datas till after the update view is done, leaving an emptry grid.
I put a little schema behind explain better the flow of my code, i hope someone can help
CODE
firstFetch(parsexml);

parsexml: function(){
//parse xml and get file list on an array
for(var i=0; i<list.length;i++){
secondFetch(parsefilelist)
}
updateView;
}
parsefilelist: function(){
//parse the corresponding file of the array and get data
}

Basically no secondFetch(parsefilelist) gets fired till after the update view, after which they all get fired in sequence. It this a normal behavior of not being able to call a fetch inside a function called after a fetch finishes? Should i rewrite the logic of my widget to avoid making this?

by
10 Replies
  • Just to be clear i always made asynch fetch as stated in the developer guide, it seems that basically the code is compiled too fast before the fetch can finish to load the data for the secondfetch, any way around this that't different than creating another view where i pass the data the first fetch finds and doing there the second fetch?
    0
  • The issue is your approach to Async calls. The platform does not wait for it to complete and return a value - hence asynchronous.

    You would be best served to use the Message Center functionality and listen for all the data that you need to be be load.
    0
  • I tried looking at the message center but can't really understand how to efficiently use it for my case, what i though was to use the message center to store the message at the end of the first fetch, and if i understood correctly everytime the hash table is changed an event onBroadcast is launched, so i must catch this event somewhere and then do the second fetch, this way i'm sure i have all the data i need?
    The onBroadcast event can be subscribed by any control? Can an event be subscribed to a function or should i need to subscribe it only to a button/element?
    0
  • Let us fool around with this and post something back.
    0
  • Try something like this.

    In your view:

    CODE
    var View = new KONtx.Class({
    config: {list:[]},
    createView: function() {
    ....
    this.updatebyfeed.subscribeTo(KONtx.messages, KONtx.messages.eventType, this);
    },

    updatebyfeed: function(event) {
    //Refresh the view if the message center gives you a value you are looking for
    if($contains(event.payload.key,this.config.list)) //"list variable is based off your previous code (see below)
    {
    print('UPDATE BUTTONS: '+event.payload.key+' -> ??? '+$contains(event.payload.key,this.config.list));
    this.updateView();
    }
    },

    });


    the functions for calling your data and storing the data in the message center

    CODE
    function loader(path, label)
    {
    var request = new URL();
    request.location = path;
    request.label = label; //We use this later to get the name of the data from the message center
    request.fetchAsync(finisher);
    }

    function finisher(request)
    {
    if ( request.response == 200 )
    {
    KONtx.application.setNetworkRequestFailed(false);
    KONtx.messages.store(request.label, JSON.parse(request.result) ); //store the information in the message center which fires event
    }
    else
    {
    print('\n\n\nDEAD NETWORK\n\n\n');
    KONtx.application.setNetworkRequestFailed(true);
    }
    }


    So how would this be used in your example:
    parsexml: function(){
    //parse xml and get file list on an array
    for(var i=0; i<list.length;i++){
    this.config.list.push(list[i].id);
    loader("http://....", list[i].id);
    }
    }
    0
  • Here is a video with Jeremy Johnstone (the guy who wrote most of the Y! Connected TV code) talking about sync calls. I would suggest watching this video for details on sync calls.

    http://video.yahoo.com/watch/8380188/22431903

    Probably not much help for you here but still good info :)
    0
  • Thanks, i'll try it
    0
  • Ok it seems i have a problem with the method you suggested, probably because i have a little problem understanding all the mechanics on how it works.

    I defined the functions you suggested and i'm using them this way
    CODE
    findDataListXML:  function(response,extra){ //this is the return function from the first network request
    ...
    var list = extra.view.config.Feed_XML.evaluate("wddxPacket/data/struct/var/array/struct");
    for(var i=0; i<list.length;i++){
    extra.view.config.list2.push({srcID:"http://provatv/wddx/IT/contenuti/"+list.item(i).evaluate("string(var[@name='id']/number)")).replace(".0","")+".xml"}); extra.view.config.Video_list.push({srcID:"http://provatv/wddx/IT/contenuti/"+list.item(i).evaluate("string(var[@name='id']/number)")).replace(".0","")+".xml",smilVideo:(list.item(i).evaluate("string(var[@name='url_tn']/string)")).replace("/1.jpg",".xml")});
    }
    for(var i=0; i<lis2t.length;i++){
    extra.view.config.list2.push(extra.view.config.list2[i].id);
    extra.view.loader(extra.view.config.Video_list[i].srcID, extra.view.config.list2[i].id);
    }
    }
    ......
    }
    updatebyfeed: function(event) {
    //Refresh the view if the message center gives you a value you are looking for
    if($contains(event.payload.key,this.config.list2)) //"list variable is based off your previous code (see below)
    {
    print('UPDATE BUTTONS: '+event.payload.key+' -> ??? '+$contains(event.payload.key,this.config.list2));
    this.updateView();
    }
    },

    loader: function(path, label)
    {
    var request = new URL();
    request.location = path;
    request.label = label; //We use this later to get the name of the data from the message center
    request.fetchAsync(this.finisher);
    },

    finisher: function(request)
    {
    if ( request.response == 200 )
    {
    KONtx.application.setNetworkRequestFailed(false);
    KONtx.messages.store(request.label, XMLDOM.parse(request.result) ); //store the information in the message center which fires event
    }
    else
    {
    print('\n\n\nDEAD NETWORK\n\n\n');
    KONtx.application.setNetworkRequestFailed(true);
    }
    },

    Problem is, it launches an enormous amount of network requests, redoing the whole parsing of the video list every time, i think i'm obviously doing something wrong but i can't get where
    0
  • It is going to launch a bunch of network requests - that is how we understood the issue was needed.

    You will need to check in your code for all the items to return by doing "something" in the event handler function to see if all the information has been returned.
    0
  • Try something like this. There are better ways to do it, just off the top of my head.

    CODE
    updatebyfeed: function(event) {	
    //Refresh the view if the message center gives you a value you are looking for
    if($contains(event.payload.key,this.config.list2)) //"list variable is based off your previous code (see below)
    {
    print('UPDATE BUTTONS: '+event.payload.key+' -> ??? '+$contains(event.payload.key,this.config.list2));
    if(!this.config.list2_temp) {this.config.list2_temp = []; }
    this.config.list2_temp.push(event.payload.key)
    if(this.config.list2.length == this.config.list2_temp.length)
    {
    this.updateView();
    }
    }
    },
    0

Recent Posts

in General - Yahoo! TV Widgets