Using jquery $.ajax causes browser lock-up with arbor.js but 'native' JSON doesn't?

1.4k Views Asked by At

I'm making a Force Directed Graph of semanticproxy.com data using this arbor fork. I have a main Explorer object which controls the nodes (following is abbreviated):

function Explorer(canvas) {
  // set up particle system
  this.ps = arbor.ParticleSystem(1000, 600, 0.5);
  this.ps.renderer = Renderer(canvas);
  this.canvas = $(canvas).get(0);

  var self = this;

  $('body').bind('subjectFound', function(event, sourceNode, targetName, targetRelevance) {
    self.addEdge(sourceNode, targetName, targetRelevance);
  });
}

Explorer.prototype.addEdge = function(source, target, relevance) {  
  var target = this.ps.addNode(target);
  if (source != target) this.ps.addEdge(source, target, {relevance:relevance});
}

// start the explorer up on a new subject
Explorer.prototype.start = function(name) {
  var node = this.ps.addNode(name);
  node.populate(this.ps);
};

var xplor = new Explorer("#viewport");
xplor.start("Andreas Michl");

You'll notice that the start() method adds a node to the particle system (works great), and then populates that node. Here's the code for the node, in part (please note that I'm augmenting the arbor.js Node prototype):

// fills this node with data from SemanticProxy
Node.prototype.populate = function() {
  var self = this;

  // get the semantic data for this subject      
  // setup the handler function
  var functionName = "subjectHandler" + new Date().getTime();
  window[functionName] = function(data) {
    // invoke function with saved context and parameter    
    self._fillFromSP.call(self, data);    
  }
  var url = "http://service.semanticproxy.com/processurl/"+SP_KEY+"/jsonp:"+functionName+"/http://en.wikipedia.org/wiki/"+this.name;
  $.ajax({url: url, dataType: "script", type: "GET", cache: false, callback: null, data: null});
};

// fills this subject with data from SemanticProxy
Node.prototype._fillFromSP = function(data) {
  var self = this;
  $.each(data, function(key, val) {
    if (key != "doc") {
      if (val.name && val.relevance) {
        $('body').triggerHandler('subjectFound', [self, val.name, val.relevance]);
      }
    }
  });
}

So once the semanticproxy data is returned it should trigger the 'subjectFound' handler in the Explorer object and add a node, just like it did before with the first node. But it chokes every time - the diagram locks up and the usage on one of my cpu cores hits 100% (Firefox and Chrome).

However, if I change the populate method to the following, it works fine:

Node.prototype.populate = function() {
  var self = this;

  // get the semantic data for this subject
  // setup the handler function
  var functionName = "subjectHandler" + new Date().getTime();
  window[functionName] = function(data) {
    // invoke function with saved context and parameter    
    self._fillFromSP.call(self, data);    
  }
  window[functionName](json);
};

var json = {"doc":{"info"  ...  "length":48}]}};

where the json variable holds the data from the very same semanticproxy URL as before. All the relevant nodes appear and render beautifully. So it's only when I use the $.ajax call, and it's only when the data actually get's back to my browser that it locks up. I can step through the code and it calls the $('body').triggerHandler with the correct parameters the correct number of times. It successfully triggers everything to the Explorer.addEdge() call where the arbor particle system is told to add some nodes - and that's when it doesn't work. But only when using the AJAX call!

Any ideas? Thanks in advance.

Update: I just set up a little Rails controller to use as a proxy. No luck either. Instead of the $.ajax call and the weird window handler, in the populate method I just did a straight:

var url = "http://localhost:3000/?url=http://service.semanticproxy.com/processurl/8bv73k5hgj9prkhee9rrr9s4/json/http://en.wikipedia.org/wiki/Andreas_Michl";
$.getJSON(url, function(data) {
  self._fillFromSP(data); 
});

But that had the same behaviour - lock-up. Maybe a race condition or something else in the arbor code?

Solution

The populate method now reads:

// fills this node with data from Wikipedia and SemanticProxy
Node.prototype.populate = function() {
  var self = this;

  // get the semantic data for this subject  
  var ajaxWorker = new Worker('javascripts/worker_ajax.js');
  ajaxWorker.onmessage = function(event) {    
    self._fillFromSP(event.data);
  };
  ajaxWorker.postMessage({name: this.name});
};

and worker_ajax.js is:

onmessage = function(event) {
  var SP_KEY = "xxxx";
  var url = "http://service.semanticproxy.com/processurl/"+SP_KEY+"/jsonp:handle/http://en.wikipedia.org/wiki/"+event.data.name;
  importScripts(url);
}

var handle = function(json) {
  postMessage(json);
}
1

There are 1 best solutions below

2
On BEST ANSWER

WebWorkers and JSONP don't go together, because WebWorkers have no DOM to attach elements to, in other words you cannot attach your script tag to anywhere.

Read this article for a possible work-around: http://cggallant.blogspot.com/2010/10/jsonp-overview-and-jsonp-in-html-5-web.html

As for using JQuery in Webworkers, take a look at this topic: HTML Web Worker and Jquery Ajax call