Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Как-то странно работает код. Не выполняется целиком функция (https://javascript.ru/forum/jquery/78921-kak-stranno-rabotaet-kod-ne-vypolnyaetsya-celikom-funkciya.html)

Yuriy-155 22.11.2019 15:03

Как-то странно работает код. Не выполняется целиком функция
 
Добрый день! Уже третий день пытаюсь понять почему так работает код.
Есть функция, которая срабатывает при выборе имени в селекте:
$('#select-name').change(function(){
        var year = '2018';
        $('.money-wrapper').empty();
        $('.money-account').hide();
        $('#add-item-money').hide();
        $('.years, .statistic, .saving-account').show();
        $('.wrap-money-curent-year').empty();
        var name = ($(this).val());
        getYears(name, year);   //вызов функции генерации кнопки "года"
        if ($('.years button').hasClass('active')) {
            year = $('.years').find('button.active').val();
        } else {
            $('.years button').first().addClass('active');
            year = $('.years').find('button.active').val();
            console.log('no class');
        } 
    });

Функция getYears(name, year) посылает ajax-запрос на сервер. С сервера приходит массив с годами, которые есть в БД и потом генерируются кнопки button, при этом если год из БД равен переменной year, то кнопке добавляется класс active:
function getYears(name, year){
    $.ajax({
        type: "POST",
        url: "getYears.php",
        data: {name: name},
        dataType: 'json',
        beforeSend: function(){
            $('.loader-wrap').css('z-index', '999').show();    
        },
        complete: function(){
             $('.loader-wrap').css('z-index', '0').hide();
        },
        success: function(data){
            switch(data.length) {
                case 0:
                    $('.years').append('<button class="btn-style" id ="add-first-item">Новая запись</button>');
                    $('#add-item-money').hide();
                    break;
                case 1:
                    $('.years').append('<button class="year active" id ="'+data[0]+'" value="'+data[0]+'">'+data[0]+'</button>');
                    break;
                default:
                    console.log(typeof data[0]);
                    console.log(typeof year);
                    for(var k in data){
                        if (parseInt(data[k]) == parseInt(year)) {
                            $('.years').append('<button class="year active" id ="'+data[k]+'" value="'+data[k]+'">'+data[k]+'</button>');
                        } else {
                            $('.years').append('<button class="year" id ="'+data[k]+'" value="'+data[k]+'">'+data[k]+'</button>');
                        }    
                    }
                    break;
            }
        }
    });
};


Я мыслил так: Выбирается имя в select, вызывается функция getYears(name, year), а там через ajax с сервера получает список 'годов' и после возвращения ответа от сервера переходит в функцию success и там генерируются кнопки. Потом функция getYears(name, year) завершает свою работу и выполняется код
if ($('.years button').hasClass('active')) {
            year = $('.years').find('button.active').val();
        } else {
            $('.years button').first().addClass('active');
            year = $('.years').find('button.active').val();
            console.log('no class');
        }

Но если выполнить скрипты пошагово видно, что выполняется функция getYears(name, year) только до функции complete (при этом достаются данные из сервера), но на success не идет, а выходит из функции getYears(name, year) и начинает проверку if... Потом в конце функции change генерируются кнопки. То есть происходит ситуация, когда проверка на существование класса active (if ($('.years button').hasClass('active'))...) происходит тогда, когда кнопки еще не сгенерировались. Не могу понять почему функция getYears(name, year) не отрабатывает полностью. если посмотреть в Консоль, срабатывает такая последовательность:
console.log('no class');
console.log(typeof data[0]);
console.log(typeof year);
А должно теоретически:
console.log(typeof data[0]);
console.log(typeof year);
console.log('no class');

Может я запутанно рассказал, но может все таки кто-то подскажет. Моих знаний уже не хватает,чтобы понять почему так работает функция. Может где-то ошибка есть, но я ее не вижу.

рони 22.11.2019 15:14

Yuriy-155,
может вы не учитываите, что строка getYears(name, year) сработает позднее, чем любые строки после неё?

Yuriy-155 22.11.2019 15:38

Цитата:

Сообщение от рони (Сообщение 515982)
Yuriy-155,
может вы не учитываите, что строка getYears(name, year) сработает позднее, чем любые строки после неё?

А почему позднее? инструкции выполняются сверху вниз последовательно, может я не прав или ест нюанс? До строки getYears(name, year) все идет последовательно.

рони 22.11.2019 15:45

Цитата:

Сообщение от Yuriy-155
А почему позднее?

потому что нужно время пока ответит сервер, если нужно запустить код после этой строки, нужно эти строки перенести в метод success

Yuriy-155 22.11.2019 15:54

Цитата:

Сообщение от рони (Сообщение 515991)
потому что нужно время пока ответит сервер, если нужно запустить код после этой строки, нужно эти строки перенести в метод success

Спасибо, этого я и не знал. Я думал, что код дальше не пойдет пока не получит ответ от сервера и не отработает success. Наверное причина в этом и есть.
А есть метод приостановить выполнения кода пока не будет получен ответ от сервера?

рони 22.11.2019 16:02

Цитата:

Сообщение от Yuriy-155
А есть метод приостановить выполнения кода пока не будет получен ответ от сервера?

можно, но зачем? разве что, для того чтобы распугать клиентов "заснувшим" браузером.

рони 22.11.2019 16:06

Цитата:

Сообщение от Yuriy-155
$.ajax

Цитата:

async:boolean(true)
По умолчанию, все запросы без перезагрузки страницы происходят асинхронно (то есть после отправки запроса на сервер, страница не останавливает свою работу в ожидании ответа). Если вам понадобиться синхронное выполнение запроса, то установите параметр в false. Кроссдоменные запросы и запросы типа "jsonp" не могут выполняться в синхронном режиме.
Имейте ввиду, что выполнение запросов в синхронном режиме может привести к блокировке страницы, пока запрос не будет полностью выполнен.
:-?

Yuriy-155 22.11.2019 16:14

Спасибо за ответ!


Часовой пояс GMT +3, время: 01:39.