問題
競合状態のように見えます。AJAX は非同期でsuccess
実行されるため、AJAX 応答が正常に受信された後、ハンドラーは将来のある時点で実行されることに注意してください。AJAX リクエストがディスパッチされている間、残りのスクリプトが実行されます。具体的に言えば:
$("body").append(html + "</div>");
成功ハンドラーが起動される前に実行されています。つまり、html
変数がまだまったく更新されていません。
解決策 1
動く
$("body").append(html + "</div>");
success
ハンドラー内。
html += "Closing tags from the header";
afterAjax();
// console.log(html); returns correct information here
$("body").append(html + "</div>");
},
解決策 2 ($.ajaxStop)
$.ajax()
呼び出しを行う前に、必ずハンドラーを登録してください。これにより、ハンドラーを に登録するコードの前に、AJAX 要求が起動して終了することがなくなります.ajaxStop
。
function loadFeeds() {
html = "";
$.ajaxStop(function(){$(document.body).append(html + "</div>);
$.each(pages, function(index, page) {
$(".pages").append("<a class=\"pagename\" href=\"#" + page[0] + "\">" + page[0] + "</a>");
html = "<div class=\"page\" id=\"" + page[0] + "\">";
...
}
解決策 3 (jsLint+Deffereds から)
この例は、完全に機能する jsLint リンクから取得したものです。このコードは$.ajax
、ループ内で作成されているすべてのリクエストを取得し、それらを配列に格納して、後で$.when().done()
呼び出しに適用します。$.when()
は適用された各リクエストを検査し$.ajax
、完了したら、 で指定されたハンドラを呼び出します$.done()
。各$.ajax
要求は、その応答をhtml = []
の開始時に定義された配列に格納し$.ready()
ます。遅延チェック ( $.when()
) がすべての$.ajax
要求が完了したことを確認したら、配列 ( array.join('')
) を結合して 1 つの大きな HTML ブロックを作成し、ドキュメントに追加します。次に、関数を呼び出しますafterAjax()
。
$(document).ready(function () {
var html = [];
var feeds = ["http://pulsesubscriber.appspot.com/items?feed=http://feeds.gawker.com/lifehacker/vip&jsonp=?",
"http://pulsesubscriber.appspot.com/items?feed=http://allthingsd.com/feed&jsonp=?",
"http://pulsesubscriber.appspot.com/items?feed=http://feeds.cnet.com/latestnews/pulse&jsonp=?"];
loadFeeds(feeds);
function loadFeeds(feeds) {
var requests = [];
$.each(feeds, function(index, feedUrl) {
requests.push($.ajax({
type: "GET",
url: feedUrl,
processData : true,
data: {
tagmode: "any"
},
jsonp: "jsonp",
dataType: "jsonp",
success: function(data) {
var feedElements = "<header class=\"feed-title\"><div class=\"feed-title-content\"><span class=\"feed-title-text\">" +
data.responseData.feed.title +
"</span></div></header><section class=\"row\"><div class=\"scroll-left\"></div><div class=\"row-scroll\">";
$.each(data.responseData.feed.entries, function(index,entry) {
var feedElements = '';
if (entry.image_urls.length === 0) {
feedElements += "<div class=\"tile no-img\"><title class=\"tile-title no-img\">" +
entry.title +
"</title><hr class=\"no-img hr\" /><span class=\"no-img excerpt\">" +
entry.contentSnippet +
"</span><div class=\"tile-modal\"><div class=\"article-wrapper\">\r\n<div class=\"article-header\">\r\n<a class=\"article-title-link\" target=\"_blank\" href=\"" +
entry.link +
"\">\r\n<h1 class=\"article-title\">" +
entry.title +
"</h1>\r\n</a>\r\n<h2 class=\"article-byline\">By " +
entry.author +
": " +
data.responseData.feed.title +
"</h2>\r\n</div>\r\n<hr class=\"article-hr\"/>\r\n<div class=\"article-content\">" +
entry.content +
"\r\n<a class=\"read-more\" target=\"_blank\" href=\"" +
entry.link +
"\">Read More...</a>\r\n</div>\r\n</div></div></div>\r\n";
}
else {
feedElements += "<div class=\"tile\"><img class=\"tile-image\" src=\"" +
entry.image_urls[0] +
"\" /><title class=\"tile-title\">" +
entry.title +
"</title><div class=\"tile-modal\"><div class=\"article-wrapper\">\r\n<div class=\"article-header\">\r\n<a class=\"article-title-link\" target=\"_blank\" href=\"" +
entry.link +
"\">\r\n<h1 class=\"article-title\">" +
entry.title +
"</h1>\r\n</a>\r\n<h2 class=\"article-byline\">By " +
entry.author +
": " +
data.responseData.feed.title +
"</h2>\r\n</div>\r\n<hr class=\"article-hr\"/>\r\n<div class=\"article-content\">" +
entry.content +
"\r\n<a class=\"read-more\" target=\"_blank\" href=\"" +
entry.link +
"\">Read More...</a>\r\n</div>\r\n</div></div></div>\r\n";
}
html.push(feedElements);
console.log('updated elements');
if(index == 34 ){
return false;
}
});
},
error: function(x,y,z) {
console.log(x.responseText);
}
}));
});
$.when.apply(this,requests).done(function(){
console.log('when!');
console.log(html);
$(document.body).append($(html.join('')));
afterAjax();
});
}
$("#refresh-all").click(function(){
$("body > header, body > section").remove();
$("body").removeClass("active");
loadFeeds();
});
function afterAjax() {
$(".page:first").addClass("active");
$(".tile").click(function(){
if ($(".tile-modal.tile-modal-active").length) {
$(".tile-modal.tile-modal-active").removeClass("tile-modal-active");
$(this).children(".tile-modal").addClass("tile-modal-active");
}
else {
$(this).children(".tile-modal").addClass("tile-modal-active");
$("body").addClass("active");
}
});
$(".scroll-left").hover(function(){
$(this).parent().animate({scrollLeft: 0}, 7000);
}, function() {
$(this).parent().stop();
});
$(".scroll-right").hover(function(){
$(this).parent().animate({scrollLeft: $(this).siblings(".row-scroll").width()}, 7000);
}, function() {
$(this).parent().stop();
});
}
});
一連のリクエストを実行し、それらがすべて実行されたら別のアクションを実行する場合は、Futures & Promises パターンまたは defereds を利用できます。jQuery では、これは.promise()
(Futures/Promises) または.when()
(Deffered) を介して行われます。
グローバル変数に関する注意
var html = ...
また、使用しないと変数がグローバルになることにも注意してください。これは一般的に眉をひそめています。$("body").append(html+"</div>")
成功ハンドラー内を移動して、html
としても宣言するのが最善var html
です。