Subject: Re: [CODE4LIB] Jquery jsonp question

From: Jason Casden <[email-masked]>
Date: Fri, 6 Nov 2009 11:57:58 -0500

If it works when you slow things down with alerts, it looks like you may
actually want an SJAX (!) call--I mean, if this page is pounding the browser
with tons of AJAX threads, maybe you only want to do one at a
time--Synchronously.

so, instead of:
$.getJSON("http://library.paulsmiths.edu/issnsearch/ispeerreviewed.php?i
ssn=" + issn + "&jsoncallback=?",function(json, textStatus) {
                                alert("test2");
                                allHTMLTags[i].innerHTML= "(" + issn +
") Peer Reviewed: " + json.peerreviewed;
                        });

maybe something like:

$.ajax({
  type: "GET",
  async: false,
  url: "http://library.paulsmiths.edu/issnsearch/ispeerreviewed.php?issn=" +
issn,
  dataType: "jsonp",
  success: function(json, textStatus) {
                                alert("test2");
                                allHTMLTags[i].innerHTML= "(" + issn +
") Peer Reviewed: " + json.peerreviewed;
                        }
});

Also, I agree with what other folks said about using as much jQuery as possible.

Jason

---

From: Graeme Williams <[email-masked]>
Date: Fri, 6 Nov 2009 12:49:07 -0500

The following is speculation only lightly leavened by experience.

Here's a simplified example:

     for (i=0; i<10; i++)
        {
         var thisArg =  ...  foo[i].innerHTML ... ;
         // alert("test") ;
         $.getJSON ( "http://somelibrary.org/q=" + thisArg +
"&jsoncallback=?",
                     function(data) {
                                    foo[i].innerHTML = data.bah
                                    }
                   )
         }

Now, the call to function(){} above creates a function closure, which is a
function object linked to its scope.  Because Javascript doesn't have block
scope (doesn't create a new scope for each block), the scope of all the
variables/code in the example above is the same.

What you'd like to happen in the example above is for the $.getJSON function
to be called and the request sent for i=0, then a result returned from the
remote site and the callback called, then the loop start again with i=1, and
so on.

What really happens is that Javascript is faster than the network, so the
browser runs through the loop, sending out 10 (asynchronous) requests, and
at the same time the results start to come back.  The problem is that the
callback functions for all 10 requests are bound to function closures that
share the same scope, and in particular share the variable "i".  This means
that the callback function calls collide with the loop that's sending out
requests.

When you included the call to alert(), you slowed things down so that the
first result did come back before the second request went out, the second
result before the third request, and so on.

I recommend that you try something like this:

   function goAndGetIt(thisElement)
      {
      var thisArg = ... thisElement.innerHTML ... ;
      $.getJSON ( "http://somelibrary.org/q=" + thisArg + "&jsoncallback=?",

                       function(data) {
                                      thisElement.innerHTML = data.bah ;
                                      }
                )
      }

   for (i=0; i<10; i++)
      {
      var thisElement = foo[i] ;
      goAndGetIt(thisElement) ;
      }

Each time you call goAndGetIt a new scope is created (with its own copy of
thisElement), so each function closure has its own scope.

Let me know if you'd like a more fully-worked out sample solution for your
problem.

Graeme Williams
Friend, patron & booster
Waltham Public Library
Waltham, MA

---

From: Godmar Back <[email-masked]>
Date: Fri, 6 Nov 2009 13:36:44 -0500

>  The following is speculation only lightly leavened by experience.

No, it's not speculation. You are correct.

 - Godmar

---

From: Michael Beccaria <[email-masked]>
Date: Fri, 6 Nov 2009 15:00:47 -0500

So I tried some different solutions that were posted and I still can't
get it to work. Here is my latest attempt as per the advice of Graeme.
This still pounds my server and freezes my browser. I'm probably going
to try a different route (static link to an informational page), but I
wanted to thank everyone who wrote back for their help. Of course, I am
still open to suggestions if more arise. Here's my latest unsuccessful
try:

<script type="text/javascript">
var allHTMLTags = new Array();
function goAndGetIt(thisElement)
{
	var originalTag = thisElement.innerHTML;
	var issn = originalTag.replace("(","").replace(")","");
	
$.getJSON("http://library.paulsmiths.edu/issnsearch/ispeerreviewed.php?i
ssn=" + issn + "&jsoncallback=?",function(json, textStatus) {
		thisElement.innerHTML= "(" + issn + ") Peer Reviewed: "
+ json.peerreviewed;
	});
}
function getElementByClass(theClass) {
	var allHTMLTags=document.getElementsByTagName("*");
	for (i=0; i<allHTMLTags.length; i++) {
		if (allHTMLTags[i].className==theClass) {

			var thisElement = allHTMLTags[i];
			goAndGetIt(thisElement);
		}
		
	}
}
window.addEvent('domReady', getElementByClass('SS_JournalISSN'));
</script>

Mike Beccaria
Systems Librarian
Head of Digital Initiatives
Paul Smith's College
518.327.6376

-----Original Message-----
From: Code for Libraries [mailto:[email-masked]] On Behalf Of
Graeme Williams
Sent: Friday, November 06, 2009 12:49 PM
To: [email-masked]
Subject: Re: [CODE4LIB] Jquery jsonp question

     for (i=0; i<10; i++)
        {

Now, the call to function(){} above creates a function closure, which is
a
function object linked to its scope.  Because Javascript doesn't have
block
scope (doesn't create a new scope for each block), the scope of all the
variables/code in the example above is the same.

What you'd like to happen in the example above is for the $.getJSON
function
to be called and the request sent for i=0, then a result returned from
the
remote site and the callback called, then the loop start again with i=1,
and
so on.

What really happens is that Javascript is faster than the network, so
the
browser runs through the loop, sending out 10 (asynchronous) requests,
and
at the same time the results start to come back.  The problem is that
the
callback functions for all 10 requests are bound to function closures
that
share the same scope, and in particular share the variable "i".  This
means
that the callback function calls collide with the loop that's sending
out
requests.

When you included the call to alert(), you slowed things down so that
the
first result did come back before the second request went out, the
second
result before the third request, and so on.

                       function(data) {

   for (i=0; i<10; i++)
      {

Each time you call goAndGetIt a new scope is created (with its own copy
of
thisElement), so each function closure has its own scope.

Let me know if you'd like a more fully-worked out sample solution for
your
problem.

Graeme Williams
Friend, patron & booster
Waltham Public Library
Waltham, MA

---

From: Demian Katz <[email-masked]>
Date: Fri, 6 Nov 2009 15:15:00 -0500

Have you thought about queueing these requests up instead of running them simultaneously?  For example, getElementByClass could establish an array of elements and call goAndGetIt on the first element in the array...  then the AJAX callback established by goAndGetIt could remove the processed element from the array on completion and call goAndGetIt on the next element, etc., etc.

- Demian

> Michael Beccaria
> Sent: Friday, November 06, 2009 3:01 PM