AJAX调用错误的顺序(异步)javascript

时间:2015-11-28 16:02:26

标签: javascript jquery

我正在制作一个使用API​​来获取有关节目所有季节的所有信息的功能。现在我得到了部分工作,我获取所有信息,但所有信息都是错误的顺序。我一直在寻找SO,我发现AJAX调用是异步的,并且已经做了一些研究。我仍然没有找到我在代码中编辑的确切内容以使其正常工作。我试着做这样的事情

function makelistbox(seasonnumber,count,slug) {
for (var o = 1; o < count; o++) {
    $.ajax({
        type: "GET",
        url: "https://api-v2launch.trakt.tv/shows/" + slug + "/seasons/" + seasonnumber + "/episodes/" + o,
        headers: {
            "Content-Type": "application/json",
            "trakt-api-version": "2",
            "trakt-api-key": "ACCESSKEY"
        },
        success: function (response) {
            defArr.push(response);
            $.when.apply($,defArr).done(function(){
                AppendContent();
            });
        }
    });
}

}    
function AppendContent(){
console.log(defArr);
for(var u = 0;u<defArr.length;u++){
    select.innerHTML += "<option value='s"+ defArr[u].season +"+ e +"+ defArr[u].number + "'> s" + defArr[u].season + "e" +defArr[u].number+":" + defArr[u].title + "</option>";
}
}

但是,由于每当我到达$ when.apply ...代码时,似乎都会执行ajax调用,因此无法正常工作。

这是我的原始代码

function listbox(slug){
$("#popupselect").empty();
$.ajax({
    type: "GET",
    url: "https://api-v2launch.trakt.tv/shows/"+ slug  +"/seasons?extended=full",
    headers: {
        "Content-Type": "application/json",
        "trakt-api-version": "2",
        "trakt-api-key": "ACCESSKEY"
    },
    success : function(response)
    {
        response.forEach(function (object,index) {
            makelistbox(object.number,object.aired_episodes,slug);
        });
    }
});
}
function makelistbox(seasonnumber,count,slug) {
for (var o = 1; o < count; o++) {
     $.ajax({
        type: "GET",
        url: "https://api-v2launch.trakt.tv/shows/" + slug + "/seasons/" + seasonnumber + "/episodes/" + o,
        headers: {
            "Content-Type": "application/json",
            "trakt-api-version": "2",
            "trakt-api-key": "ACCESSKEY"
        },
        success: function (response) {

            AppendContent(response);
        }
    });
}
}
function AppendContent(response){
select.innerHTML += "<option value='s"+ response.season +"+ e +"+ response.number + "'> s" + response.season + "e" +response.number+":" + response.title + "</option>";
}

我的目标是将每季剧集的季节编号和剧集编号以及剧集标题添加到列表框中。我无法按正确的顺序工作......

提前致谢!

编辑 - 编辑 - 编辑 - 编辑 - 编辑 - 编辑 - 编辑 - 编辑 - 编辑 - 编辑

@ Arg0n 好吧,我一直在尝试为我的季节做这件事,但它并没有真正成功。从您的代码和链接我假设我必须从季节的ajax调用中创建一个数组,所以我这样做(基本上这意味着我有一个嵌套的promises函数吗?)。我的代码现在没有给出任何错误,但它也没有按照我想要的方式工作。意思是我的剧集仍然排序,感谢你,但我的季节仍然没有

function listbox(slug){
$("#popupselect").empty();
var arrPromise =[];
arrPromise.push(
$.ajax({
    type: "GET",
    url: "https://api-v2launch.trakt.tv/shows/"+ slug  +"/seasons?extended=full",
    headers: {
        "Content-Type": "application/json",
        "trakt-api-version": "2",
        "trakt-api-key": "ACCESSKEY"
    },
    success: function(response) {
        Promise.all(arrPromise).then(function(content){
            for(var z=0; z< content.length;z++){
                response.forEach(function (object,index) {
                    console.log("chec");
                    makelistbox(object.number,object.aired_episodes,slug);
                });
            }
        })
    }
}));
}

2 个答案:

答案 0 :(得分:0)

基本上,Promises.all()可以让您执行以下操作:

var promises = [];
for(var i = 0; i < 5; i++){
    promises.push($.ajax("SomeURL"));
}
Promise.all(promises).then(function(datas){
   for(var y = 0; y < datas.length; y++){
        var data = datas[y]; //Your data in correct order   
   }
});

等待promises中的所有请求完成,然后调用then中的函数。结果是一个包含正确顺序的数据的列表。

修改

翻译成您的代码,这将是这样的:

function listbox(slug){
    $("#popupselect").empty();
    $.ajax({
        type: "GET",
        url: "https://api-v2launch.trakt.tv/shows/"+ slug  +"/seasons?extended=full",
        headers: {
            "Content-Type": "application/json",
            "trakt-api-version": "2",
            "trakt-api-key": "ACCESSKEY"
        },
        success: function(response) {
            var promises = [];
            response.forEach(function (object,index) {
                var addPromises = makelistbox(object.number,object.aired_episodes,slug);
                for(var i = 0; i < addPromises.length; i++){
                    var promise = addPromises[i];
                    promises.push(promise);
                }
            });
            Promise.all(promises).then(function(responses){
                for(var i = 0; i < responses.length; i++){
                    AppendContent(responses[i]);
                }
            });
        }
    });
}

function makelistbox(seasonnumber,count,slug) {
    var promises = [];
    for (var o = 1; o < count; o++) {
        promises.push($.ajax({
            type: "GET",
            url: "https://api-v2launch.trakt.tv/shows/" + slug + "/seasons/" + seasonnumber + "/episodes/" + o,
            headers: {
                "Content-Type": "application/json",
                "trakt-api-version": "2",
                "trakt-api-key": "ACCESSKEY"
            }
        }));
    }
    return promises;
}

答案 1 :(得分:0)

有3种方法可以做到。

首先,最简单的方法是使AJAX调用同步,但将 async:false 添加到jQuery ajax输入中。因此,您的代码将成为

$.ajax({
    async: false, /*it's a synchronous request and thus SJAX*/
    type: "GET",
    url: "https://api-v2launch.trakt.tv/shows/"+ slug  +"/seasons?extended=full",
    headers: {
        "Content-Type": "application/json",
        "trakt-api-version": "2",
        "trakt-api-key": "ACCESSKEY"
    },
    success : function(response)
    {
        response.forEach(function (object,index) {
            makelistbox(object.number,object.aired_episodes,slug);
        });
    }
});

这将使请求顺序,但它会阻止Javascript线程继续进行,因此也会阻止UI呈现。

另一种方法是在第一个请求的成功或失败回调中进行下一个请求,这也会使请求顺序但不会阻止Javascript线程。

function makeAjaxRequest(slug, o) {
     $.ajax({
        async:false,
        type: "GET",
        url: "https://api-v2launch.trakt.tv/shows/" + slug + "/seasons/" + seasonnumber + "/episodes/" + o,
        headers: {
            "Content-Type": "application/json",
            "trakt-api-version": "2",
            "trakt-api-key": "ACCESSKEY"
        },
        success: function (response) {
            defArr.push(response);
            if(++o < count) {
                makeAjaxRequest(slug, o);
            } else {
                AppendContent(defArr);
            }
        }
    });
}

makeAjaxRequest(slug, 1);

Next方法存储回调请求编号,并使用此编号作为数组索引将响应插入临时数组中。一旦所有回调都返回响应,它也会调用AppendContent。这种方法的好处是它仍然是异步的,并且不会阻塞Javascript线程。

var responseArr = [];
var responseCallbackCount = 0;
function makeAjaxRequest(slug, o) {
     $.ajax({
        async:false,
        type: "GET",
        url: "https://api-v2launch.trakt.tv/shows/" + slug + "/seasons/" + seasonnumber + "/episodes/" + o,
        headers: {
            "Content-Type": "application/json",
            "trakt-api-version": "2",
            "trakt-api-key": "ACCESSKEY"
        },
        success: function (response) {
            respnoseArr[o-1] = response;

            if(++responseCallbackCount >=count) {
                for(var i = 0; i < responseArr.length; i++) {
                    defArr.concat(responseArr[i]);
                }
                AppendContent(defArr);
            }
        }
    });
}

for (var o = 1; o < count; o++) {
    makeAjaxRequest(slug, o);
}