1

下面的代码,当运行时,但它似乎以某种方式没有按顺序附加帖子(有时post_2是第一个和post_4第二个):

var posts = [
    "post_1.md",
    "post_2.md",
    "post_3.md",
    "post_4.md",
    "post_5.md",
    "post_6.md",
    "post_7.md"];

for (var i in posts) {
    $.ajax({
        url: "posts/" + posts[i],
        context: document.body,
        success: function (mdText) {
            var converter = new Showdown.converter();
            var htmlText = converter.makeHtml(mdText);
            $("body").append(htmlText);
        }
    });
}

它遍历数组中的元素,并为每个元素下载一个 Markdown 文档,将其转换为 HTML,并将其附加到正文中。我尝试了一个简单的for循环以及下划线的_.each()功能。所有三个都有相同的结果,运行时它们不会按顺序附加文档(所以当我单击刷新时,标题的顺序不同)。任何想法为什么会发生这种情况以及解决它的方法?

4

2 回答 2

5

$.ajax是一个异步函数,这意味着您的所有$.async函数都是并行发生的,并将按照它们完成的顺序附加到主体(这显然会根据它们获取的文档的大小和一般的网络延迟而有所不同)。

您可能希望查看async.js库,它允许您并行运行 AJAX 调用,然后在所有操作完成后执行回调。您想使用该async.parallel函数,它将每个 AJAX 调用的结果作为数组传递给最终回调。

于 2013-03-09T19:48:54.993 回答
2

这正是 jQuery 的类型,$.when旨在deferred.done提供帮助。您传递了一系列延迟(jQuery 的$.ajax返回延迟),当他们的承诺解决时,您可以单独处理它们中的每一个。这是 jQuery 的 API 文档本身的修改示例:

$.when( $.ajax("/page1.php"), $.ajax("/page2.php") ).done(function( a1, a2 ) {
  /* a1 and a2 are arguments resolved for the page1 and page2 ajax requests */
});

传入的回调函数.done只会在 promise 全部解决后运行。因此,即使对 page2 的请求可能在 page1 之前完成,我们也不担心。在所有请求完成之前,我们的代码不会被调用。

在您的特定情况下,异步请求的数量未知并且会有所不同,您可能会发现使用以下方法会更成功func.apply

var reqs = [];

reqs.push( $.ajax("post_1.md"), $.ajax("post_2.md"), $.ajax("post_3.md") );

$.when.apply(this, reqs).done(function () {
    $.each(arguments, function (index, value) {
        console.log( value[0] );
    });
});
于 2013-03-09T20:05:15.793 回答