2009-11-17 4 views
1

У меня есть сценарий Greasemonkey, который работает на странице результатов поиска на видео-сайте. Функция сценария заключается в том, чтобы взять ссылку на javascript, которая открывает новое окно с помощью флеш-плеера, перепрыгивает через некоторые переадресации и вставляет регулярную ссылку на нужный файл FLV.Вложенные XMLHttpRequests с несколькими замыканиями - хорошая идея?

Я изменил сценарий, чтобы сделать глупые, но структурно эквивалентные вещи en.wikipedia.org. Мой вопрос в том, является ли 3 вложенных замыканий и вложенными xmlhttprequests лучшим способом для этого.


// ==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 
    } 
} 
+0

Похож на классический асинхронный поток кода. В чем проблема? –

+0

Проблема в том, что это моя первая попытка написать сценарий greasemonkey, и я хочу убедиться, что я делаю это правильно. Это меньше, чем вопрос «это ошибка кода», и вопрос об этом «запах». – Bribles

+0

@Bribles: да, конечно. [Вложенный] поток асинхронного кода всегда выглядит вонючим, но он не более вонючий, что серийный код спагетти;) –

ответ

3

Ну, вы могли бы улучшить читаемость путем создания отдельных функций для каждого этапа, то с 1 этап вызова стадии 2, и т.д. Таким образом, вместо

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

вы бы

request({onload: doTheNextThing}); 

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

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

function doTheLastThing(responseObject) { 
    alert("psych!"); 
} 
+0

Это уменьшает средний уровень отступов кода. – Bribles

+0

Я считаю, что ваш ответ подчеркивает, что у меня было слишком много анонимных функций. – Bribles

1

Или, если он становится еще более сложным, вы можете порт Promises в свою любимую структуру JavaScript. Программирование AJAX принципиально нарушено. Я делаю это в течение 5 лет - 40 000 строк JS позже, это одна попытка решения.

 Смежные вопросы

  • Нет связанных вопросов^_^