简体   繁体   English

在另一个函数完成JavaScript和JQuery之后运行函数

[英]Run function after another function completes JavaScript and JQuery

I need a little help. 我需要一点帮助。 I'm trying to run my second function "likeLinks();" 我正在尝试运行第二个函数“ likeLinks();” but only after my first function "getLikeURLs();" 但仅在我的第一个函数“ getLikeURLs();”之后 is finished. 完成。 This is because my 2nd function relies on the links Array to execute. 这是因为我的第二个函数依赖于链接数组来执行。 It seems like they are trying to run at the same time. 似乎他们正在尝试同时运行。

Any help would be appreciated. 任何帮助,将不胜感激。

    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) {});
        }
    }

The link variables are actually jQuery deferred objects - store them in an array and then you can use $.when() to create a mew deferred object that only resolves when all of the previous $.get() operations have completed: link变量实际上是jQuery延迟对象 -将它们存储在数组中,然后可以使用$.when()创建喵喵延迟对象,该对象仅在所有先前的$.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; });
}

Then, to start the chain of functions: 然后,启动功能链:

getLikeURLs(url).then(likeLinks);

Note that likeLinks will now be passed the array of links instead of accessing it from the global state. 注意, likeLinks现在将通过链接数组传递,而不是从全局状态访问它。 That function should also be rewritten to allow you to wait for its $.post calls to complete, too: 该函数也应该被重写,以允许您也等待$.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);
}

ps don't put that (relatively) expensive parseInt(document.getAttribute(...)) expression within the for statement - it'll cause it to be evaluated every iteration. ps不会在for语句中放入(相对)昂贵的parseInt(document.getAttribute(...))表达式-它将导致每次迭代对其进行评估。 Calculate it once outside the loop and store it in a variable. 在循环外计算一次并将其存储在变量中。 There's a few other places where you're repeating calls unnecessarily, eg window.location.pathname.split() 在其他一些地方,您不必要地重复呼叫,例如window.location.pathname.split()

EDIT: My answer discusses the issue but see Alnitak answer for a much better solution. 编辑:我的答案讨论了这个问题,但请参阅Alnitak答案以寻求更好的解决方案。

The get in getLikeURLs and the put in likeLinks are both asynchronous. getLikeURL和getLikeLink都是异步的。 The calls to both of these function return immediately. 对这两个函数的调用将立即返回。 When data is returned from the called server at some indeterminate time later, the callback functions are then called. 在某个不确定的时间从被调用的服务器返回数据时,将调用回调函数。 The puts could return before the gets which would be a problem in your case. 认沽期权可能会在获得收益之前返回,这对您来说是个问题。 Also note that JavaScript is NOT multi-threaded so the two methods, getLikeURLs and likeLinks will never run at the same time. 还要注意,JavaScript不是多线程的,因此这两种方法getLikeURLs和likeLinks永远不会同时运行。 The callback functions, on the other hand, might be called at anytime later with no guarantee as to the call back order. 另一方面,回调函数可以在以后的任何时间调用,而不能保证回调顺序。 For example, the 3rd get/put might return before the 1st get/put in your loops. 例如,第三个get / put可能在循环中的第一个get / put之前返回。

You could use $.ajax to specify that the gets and puts are synchronous but this is ill advised because the browser will hang if ANY get/put doesn't return in a reasonable amount of time (eg server is offline). 您可以使用$ .ajax来指定gets和puts是同步的,但是不建议这样做,因为如果在合理的时间内未返回任何get / put,浏览器将挂起。 Plus you don't have the "multi-tasking" benefit of sending out a lot of requests and having the various servers working at the same time. 另外,您没有发送大量请求并使多个服务器同时工作的“多任务”优势。 They would do so serially. 他们将依次这样做。

The trick is to simply call likeLinks form the callback function in getLikeURL. 技巧是简单地从getLikeURL中的回调函数调用likeLinks。 Your case is a little tricky because of the for loop but this should work: 由于for循环,您的情况有些棘手,但这应该可行:

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) {});
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM