我需要一些帮助。我正在尝试运行我的第二个函数“likeLinks();”但只有在我的第一个函数“getLikeURLs();”之后完了。这是因为我的第二个函数依赖于链接Array来执行。看起来他们正试图同时运行。
任何帮助都将不胜感激。
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 :(得分:1)
link
变量实际上是jQuery deferred objects - 将它们存储在一个数组中,然后你可以使用$.when()
来创建一个仅在以前所有{{1}时解析的新延迟对象操作已完成:
$.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
P.S。不要在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);
}
语句中放置那个(相对)昂贵的parseInt(document.getAttribute(...))
表达式 - 它会导致每次迭代都对它进行评估。在循环外部计算一次并将其存储在变量中。还有一些其他地方您不必要地重复拨打电话,例如: for
答案 1 :(得分:0)
编辑:我的回答讨论了这个问题,但请参阅Alnitak回答更好的解决方案。
get in getLikeURLs和putLinks中的get都是异步的。对这两个函数的调用立即返回。当在稍后的某个不确定时间从被调用服务器返回数据时,然后调用回调函数。看跌期权可能会在收益之前返回,这将是您的案例中的问题。另请注意,JavaScript不是多线程的,因此getLikeURL和likeLinks这两种方法永远不会同时运行。另一方面,回调函数可能在以后的任何时候被调用,而不能保证回调订单。例如,第3次获取/放置可能会在第1次获取/放入循环之前返回。
你可以使用$ .ajax来指定获取和放置是同步的,但这是不明智的,因为如果任何get / put没有在合理的时间内返回(例如服务器离线),浏览器将挂起)。另外,你没有“多任务处理”#34;发送大量请求并使各种服务器同时工作的好处。他们会连续这样做。
诀窍是简单地在getLikeURL中调用likeLinks作为回调函数。因为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) {});
}
}