2014-10-09 5 views
0

Мне нужна небольшая помощь. Я пытаюсь запустить свою вторую функцию «likeLinks()»; но только после моей первой функции «getLikeURLs();» закончен. Это связано с тем, что моя вторая функция полагается на массив ссылок для выполнения. Похоже, они пытаются работать одновременно.Функция запуска после выполнения другой функции JavaScript и JQuery

Любая помощь будет оценена по достоинству.

var links = []; 
    var url = '/' + window.location.pathname.split('/')[1] + '/' + window.location.pathname.split('/')[2] + '/' 
    getLikeURLs(); 
    likeLinks(); 

    function getLikeURLs() { 
     for (i = 1; i < parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-last')) + 2; i++) { 
      var link = $.get(url + 'page-' + i, function(data) { 
       //gets the like links from current page 
       $(data).find('a[class="LikeLink item control like"]').each(function() { 
        links.push($(this).attr('href')); // Puts the links in the Array 
       }); 
      }); 
     } 
    } 

    function likeLinks() { 
     for (t = 0; t <= links.length; t++) { 
      var token = document.getElementsByName('_xfToken')[0].getAttribute('value') 
      $.post(links[t], { 
       _xfToken: token, 
       _xfNoRedirect: 1, 
       _xfResponseType: 'json' 
      }, function(data) {}); 
     } 
    } 
+0

вызов Ajax получить и пост, как метод асинхронном: ложный – abc123

+0

http://stackoverflow.com/questions/5000415/javascript-jquery-call-a-function-after-previous-function-is-complete – khizerbajwa

+0

@ абв123 был правильно! еще раз спасибо. :) – user3912043

ответ

1

В link переменные фактически jQuery deferred objects - хранить их в массиве, а затем вы можете использовать $.when() создать Mew отложенный объект, который только решает когда все предыдущие $.get() операции были завершены:

function getLikeURLs(url) {  // NB: parameter, not global 
    var defs = [], links = []; // NB: links no longer global 

    for (...) { 
     var link = $.get(...); 
     defs.push(link); 
    } 

    // wait for previous `$.get` to finish, and when they have create a new 
    // deferred object that will return the entire array of links 
    return $.when.apply($, defs).then(function() { return links; }); 
} 

Затем, чтобы запустить цепочку функций:

getLikeURLs(url).then(likeLinks); 

Обратите внимание, что likeLinks теперь будет передан массив ссылок вместо доступа к нему из глобального состояния. Эта функция также должна быть переписана, чтобы позволить вам ждать его $.post завершения вызовов, тоже:

function likeLinks(links) { 
    // loop invariant - take it outside the loop 
    var token = document.getElementsByName('_xfToken')[0].getAttribute('value'); 

    // create array of deferreds, one for each link 
    var defs = links.map(function(link) { 
     return $.post(link, { 
      _xfToken: token, 
      _xfNoRedirect: 1, 
      _xfResponseType: 'json' 
     }); 
    }); 

    // and another for when they're all done 
    return $.when.apply($, defs); 
} 

P.S. не ставьте это (относительно) дорогое выражение parseInt(document.getAttribute(...)) в оператор for - это заставит его оценивать каждую итерацию. Вычислите его один раз за пределами цикла и сохраните его в переменной. Есть несколько других мест, где вы повторяете вызовы без необходимости, например. window.location.pathname.split()

+0

Спасибо за это. Если вам когда-нибудь понадобится приглашение Oneplus One; PM @kallen на форумах Oneplus. – user3912043

0

EDIT: Мой ответ обсуждает вопрос, но увидеть Альнитак ответ на гораздо лучшее решение.

Входящие в getLikeURLs и помеченные как likeLinks являются асинхронными. Звонки на обе эти функции возвращаются немедленно. Когда данные возвращаются с вызываемого сервера через какое-то неопределенное время позже, тогда вызываются функции обратного вызова. Поставы могут вернуться до того, что будет проблемой, которая будет проблемой в вашем случае. Также обратите внимание, что JavaScript не является многопоточным, поэтому два метода: getLikeURL и likeLinks никогда не будут запускаться одновременно. С другой стороны, функции обратного вызова могут быть вызваны в любое время позже без каких-либо гарантий относительно порядка обратного вызова. Например, 3-й get/put может вернуться до 1-го get/put в ваших циклах.

Вы можете использовать $ .ajax, чтобы указать, что get и puts являются синхронными, но это не рекомендуется, так как браузер будет зависать, если ANY get/put не вернется в течение разумного промежутка времени (например, сервер находится в автономном режиме) , Кроме того, у вас нет «многозадачного» преимущества для отправки большого количества запросов и одновременного использования разных серверов. Они будут делать это последовательно.

Трюк состоит в том, чтобы просто вызвать likeLinks из функции обратного вызова в getLikeURL. Ваше дело немного сложнее из-за цикл, но это должно работать:

var links = []; 
    var url = '/' + window.location.pathname.split('/')[1] + '/' + window.location.pathname.split('/')[2] + '/' 
    getLikeURLs(); 
    //likeLinks(); // Don't call yet. Wait for gets to all return. 

    function getLikeURLs() { 
     var returnCount = 0; // Initialize a callback counter. 
     var count = parseInt(document.getElementsByClassName('PageNav')[0].getAttribute('data-last')) + 1; 
     for (i = 0; i < count; i++) { 
      var link = $.get(url + 'page-' + (i + 1), function(data) { 
       //gets the like links from current page 
       $(data).find('a[class="LikeLink item control like"]').each(function() { 
        links.push($(this).attr('href')); // Puts the links in the Array 
       }); 

       // If all gets have returned, call likeLinks. 
       returnCount++; 
       if (returnCount === count) { 
        likeLinks(); 
       } 
      }); 
     } 
    } 

    function likeLinks() { 
     for (t = 0; t <= links.length; t++) { 
      var token = document.getElementsByName('_xfToken')[0].getAttribute('value') 
      $.post(links[t], { 
       _xfToken: token, 
       _xfNoRedirect: 1, 
       _xfResponseType: 'json' 
      }, function(data) {}); 
     } 
    } 
+0

это (ИМХО) наивный метод pre-jQuery 1.5. Просто используйте '$ .when' вместо этого! – Alnitak

+0

Хорошо объяснил, однако, Марк. +1 от меня. – GregL

+0

-1, потому что он (излишне) плотно соединяет вызов 'likeLinks' внутри функции getLikeURLs(). – Alnitak

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