Кілька запитів на ajax

так що це моя установка: я закликаю .each на кілька елементів і після декількох перевірок я посилаю AJAX запит з деякими даними JSON і на успіх я застосовую відповідь сервера як атрибут для кожного елемента (як правило id). Після цього натискаю id в масив.

Проблема в тому, що, очевидно, аякс-запити асинхронні, а функція, яка використовує масив елементів ідентифікаторів елементів, перед тим, як всі ajax встигли закінчити.

Я намагався з .when і .then, але функція зворотного виклику продовжує отримувати звільнені шлях попереду ajax.

Ось як виглядає мій код (я видалив деякі непотрібні частини):

var order = [];

function sub(selector){

selector.each(function(){
    var out = {
        "some":"random",
        "stuff":"here"
    };
        $.ajax({
            type: "POST" 
            url: "/test/url",
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify(out),
            success:function(response){
                $(this).attr("data-response",response);
                order.push(response);
            }
        })
    })
}

$("#button").click(function(){
    $.when(sub($(".test"))).then(function() {
        console.log(order);
        //i have to run the sub function twice so the order doesn't return undefined
    });     
});
1
Ви можете продовжувати перевірку кількості itmes в порядку масиву, поки він не матиме такого ж розміру, як у selector.each. за допомогою setInterval
додано Автор bitkot, джерело
Ви можете продовжувати перевірку кількості itmes в порядку масиву, поки він не матиме такого ж розміру, як у selector.each. за допомогою setInterval
додано Автор bitkot, джерело

7 Відповіді

Додати атрибут async: false до вашого $ .ajax - виклику. Потім дзвінки виконуються послідовно після того, як один.

2
додано
Так, це зробить його повільніше. Я просто відповів на запитання, і він буде працювати. Якщо peformance є проблемою OP, слід переписати код, так що для кожного виклику функції виконується лише один запит сервера (якщо це можливо)
додано Автор bestprogrammerintheworld, джерело
що зробить речі ще повільнішими
додано Автор Alp, джерело
Це погане рішення - є дуже гарна причина для використання асинхронних викликів.
додано Автор Tomer Arazy, джерело

Додати атрибут async: false до вашого $ .ajax - виклику. Потім дзвінки виконуються послідовно після того, як один.

2
додано
Так, це зробить його повільніше. Я просто відповів на запитання, і він буде працювати. Якщо peformance є проблемою OP, слід переписати код, так що для кожного виклику функції виконується лише один запит сервера (якщо це можливо)
додано Автор bestprogrammerintheworld, джерело
що зробить речі ще повільнішими
додано Автор Alp, джерело
Це погане рішення - є дуже гарна причина для використання асинхронних викликів.
додано Автор Tomer Arazy, джерело

Проблема полягає в тому, що , коли діє на відкладені об'єкти, однак, sub не повертає нічого, так що коли відразу спрацьовує. Так що вам потрібно зробити, це зібрати всі відкладені об'єкти, повернуті викликами ajax і повернути їх:

var order = [];

function sub(selector){
    var deferredList = []
    selector.each(function(){
        var out = {
            "some":"random",
            "stuff":"here"
        };
        var deferred = $.ajax({
                type: "POST", 
                url: "/test/url",
                dataType: 'json',
                contentType: "application/json; charset=utf-8",
                data:JSON.stringify(out),
                success:function(response){
                    $(this).attr("data-response",response);
                    order.push(response);
                }
            })
        deferredList.push(deferred)
    })
    return deferredList;
}

$("#button").click(function(){
    $.when.apply($,sub($(".test"))).then(function() {
        console.log(order);
        //i have to run the sub function twice so the order doesn't return undefined
    });     
});

Причиною використання застосувати , а не при безпосередньому є те, що коли не приймає масив об'єктів як параметр і застосовується надає нам роботу для цього.

1
додано
це також спрацьовує перед усім ajax (всі значення масиву замовлень не визначені)
додано Автор Jon Snow, джерело
Так, насправді, все добре.
додано Автор Jon Snow, джерело
Працює для мене, можливо, проблема у вашому коді є десь ще
додано Автор Tomer Arazy, джерело

Проблема полягає в тому, що , коли діє на відкладені об'єкти, однак, sub не повертає нічого, так що коли відразу спрацьовує. Так що вам потрібно зробити, це зібрати всі відкладені об'єкти, повернуті викликами ajax і повернути їх:

var order = [];

function sub(selector){
    var deferredList = []
    selector.each(function(){
        var out = {
            "some":"random",
            "stuff":"here"
        };
        var deferred = $.ajax({
                type: "POST", 
                url: "/test/url",
                dataType: 'json',
                contentType: "application/json; charset=utf-8",
                data:JSON.stringify(out),
                success:function(response){
                    $(this).attr("data-response",response);
                    order.push(response);
                }
            })
        deferredList.push(deferred)
    })
    return deferredList;
}

$("#button").click(function(){
    $.when.apply($,sub($(".test"))).then(function() {
        console.log(order);
        //i have to run the sub function twice so the order doesn't return undefined
    });     
});

Причиною використання застосувати , а не при безпосередньому є те, що коли не приймає масив об'єктів як параметр і застосовується надає нам роботу для цього.

1
додано
це також спрацьовує перед усім ajax (всі значення масиву замовлень не визначені)
додано Автор Jon Snow, джерело
Так, насправді, все добре.
додано Автор Jon Snow, джерело
Працює для мене, можливо, проблема у вашому коді є десь ще
додано Автор Tomer Arazy, джерело

Аргумент $ .when() має бути Відкладений , але sub() нічого не повертає. Ця версія повертає масив усіх Відкладених , повернутих $ .ajax , і викликає $ .when разом з усіма як аргументи; потім він чекає всіх.

var order = [];

function sub(selector){
    return selector.map(function(){
        var out = {
            "some":"random",
            "stuff":"here"
        };
        return $.ajax({
            type: "POST" 
            url: "/test/url",
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify(out),
            success:function(response){
                $(this).attr("data-response",response);
                order.push(response);
            }
        })
    })
}

$("#button").click(function(){
    $.when.apply(this, sub($(".test"))).then(function() {
        console.log(order);
        //i have to run the sub function twice so the order doesn't return undefined
    });     
});
0
додано
$ .ajax() повертає об'єкт jqXHR , який реалізує інтерфейс Promise на додаток до специфічних для AJAX методів, таких як .done ( ) .
додано Автор Barmar, джерело
Я спробував це, але він все ще спрацьовує перед тим, як закінчився аякс
додано Автор Jon Snow, джерело
не повинно бути success методом повернутого об'єкта, заданого $ .ajax ?
додано Автор Alp, джерело

спробувати використати функцію зворотного виклику в успіху:

var order = [];

function sub(selector, callback){

selector.each(function(){
    var out = {
        "some":"random",
        "stuff":"here"
    };
        $.ajax({
            type: "POST" 
            url: "/test/url",
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify(out),
            success:function(response){
                $(this).attr("data-response",response);
                order.push(response);
                callback();
            }
        })
    })
}

$("#button").click(function(){
    sub($(".test"), function() { console.log(order) });
});
0
додано

Ваш підхід створює багато запитів на сервер і масштабно масштабується. Оскільки ви все одно хочете чекати всіх результатів, набагато краще рішення буде зібрати всі дані і надіслати лише один запит ajax, який повертає масив результатів для кожного об'єкта даних.

Використання відкладеного об'єкта (як видно з інших відповідей) дає вам можливість використовувати цей результат у операторі коли .

0
додано
ІТ КПІ - JavaScript
ІТ КПІ - JavaScript
504 учасників

співтовариство javascript розробників в Telegram