English 中文(简体)
Is nested XMLHttpRequests with multiple closures a good idea?
原标题:

I have a Greasemonkey script which operates on a search results page at a video site. The function of the script is to take a javascript link that opens a new window with a flash player, jump through some redirection hoops, and insert a regular link to the desired FLV file.

I have changed the script to do silly but structurally equivalent things to en.wikipedia.org. My question is whether the 3 nested closures and the nested xmlhttprequests is the best way to go about this.


// ==UserScript==
// @name                wiki mod example
// @namespace         http://
// @description         example script
// @include  *wikipedia.org*
// ==/UserScript==

var candidates = document.getElementsByTagName("a");

for (var cand = null, i = 0; (cand = candidates[i]); i++) {
  if (cand.href.match(//wiki/W/)) { // for all articles starting with  W 
    var progress = document.createElement( span );
    progress.appendChild(document.createTextNode(" Start"));
    cand.parentNode.insertBefore(progress, cand.nextSibling);
    progress.addEventListener("click",
    function(link1) { return function() { // link1 is cand.href
      this.innerHTML = " finding...";

      GM_xmlhttpRequest({method:"GET",url:link1,
        onload:function(p) { return function(responseDetails) {
          // p is is the current progress element
          // the first linked article starting with  S  is *special*
          var link2 = responseDetails.responseText.match(//wiki/S[^"]+/);
          if(!link2) { p.innerHTML = "failed in request 1"; return;}

          GM_xmlhttpRequest({method:"GET",url:"http://en.wikipedia.org"+link2[0],
            onload:function(p2) { return function(responseDetails) {
              // p2 is p, ie. progress
              // link3 would contain the URL to the FLV in the real script
              var link3 = responseDetails.responseHeaders.match(/Content-Length.+/);
              if(!link3) { p2.innerHTML = "failed in request 2"; return;}

              var elmNewContent = document.createElement( p );
              elmNewContent.appendChild(document.createTextNode(link3));
              p2.parentNode.insertBefore(elmNewContent, p2.nextSibling);
              p2.innerHTML = " <em>Done</em>";
            }}(p) // 3rd closure
          }); // end of second xmlhttprequest

        }}(this) // 2nd closure
      }); // end of first xmlhttprequest

    }}(cand.href), true); // 1st closure and end of addeventlistener
  } 
}
最佳回答

Well, you could improve readability by creating separate functions for each stage, then having stage 1 call stage 2, etc. So, instead of

request({onload: function(response) {
    request({onload: function(response) {
        request({onload: function(response) {
            alert("psych!");
        }});
    }});
}});

you d have

request({onload: doTheNextThing});

function doTheNextThing(responseObject) {
    request({onload: doTheRightThing});
}

function doTheRightThing(responseObject) {
    request({onload: doTheLastThing});
}

function doTheLastThing(responseObject) {
   alert("psych!");
}
问题回答

When this gets more complicated, you might consider a state machine. http://www.ibm.com/developerworks/library/wa-finitemach1/

Or if it gets even more complicated you can port Promises to your favorite JavaScript framework. AJAX programming is fundamentally broken. I ve been doing it for 5 years - 40,000 lines of JS later this one attempt at a solution.





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签