Функция Javascript запускается только один раз? Попытка использовать одну и ту же функцию несколько раз

#javascript #html

#javascript #HTML

Вопрос:

Как следует из названия, я пытаюсь использовать одну и ту же функцию javascript несколько раз на одной странице. В принципе, у меня есть 2 отдельных выпадающих списка, которые вызывают пользователей через ajax, так что будут присутствовать даже новые пользователи. (Сайт основан на том, что не нужно всегда перезагружать.) В любом случае, способ, которым я в настоящее время ее настраиваю, примерно такой…

Javascript:

 function getAllUsers() {
        (function getAllUsers() {
            $.ajax({
                url: 'staff/getAllUsers.php',
                success: function(data) {
                    $('#getAllUsers').html(data);
                },
                complete: function() {
                    // Schedule the next request when the current one's complete
                    setTimeout(getAllUsers, 5000);
                }
            });
        })();
    }
    getAllUsers();

function getAllUsers2() {
    (function getAllUsers2() {
        $.ajax({
            url: 'staff/getAllUsers.php',
            success: function(data) {
                $('#getAllUsers2').html(data);
            },
            complete: function() {
                // Schedule the next request when the current one's complete
                setTimeout(getAllUsers2, 5000);
            }
        });
    })();
}
getAllUsers2();
  

Я уверен, что делать это подобным образом непрактично, поэтому я прошу некоторых указаний сейчас.

Это текущая настройка HTML для нее в выпадающих списках:

 <select class="select2" name="user" id="getAllUsers" required>
    <option selected="true" disabled="disabled">Loading Users...</option>
</select>

<select class="select2" name="user" id="getAllUsers2" required>
    <option selected="true" disabled="disabled">Loading Users...</option>
</select>
  

Очевидно, что опция загрузки пользователей … заменяется при загрузке данных ajax.

Опять же, я уверен, что существует лучший способ сделать это.

Но всякий раз, когда я пытаюсь сделать что-то подобное с html … используя ту же функцию javascript, вторая просто остается на «Загрузка пользователей …»

 <select class="select2" name="user" id="getAllUsers" required>
    <option selected="true" disabled="disabled">Loading Users...</option>
</select>

<select class="select2" name="user" id="getAllUsers" required>
    <option selected="true" disabled="disabled">Loading Users...</option>
</select>
  

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

Спасибо за любую помощь!

Комментарии:

1. Почему у вас есть функция с тем же именем в IIFE? Что это значит для выполнения?

2. @JackBashford собирался удалить это, просто есть другие более важные дела, хаха. Я знаю, что этого не должно быть, хотя.

3. передать идентификатор в качестве параметра?

4. Вы пытаетесь использовать один и тот же идентификатор тега для двух разных элементов, но один и тот же идентификатор может появиться только один раз в вашем дереве DOM.

Ответ №1:

Оба select2 используют одну и ту же конечную точку, почему бы просто не присвоить значение в одном и том же ajax-запросе?

Что-то вроде этого будет в порядке:

 function getAllUsers() {
  $.ajax({
    url: 'staff/getAllUsers.php',
    success: data => {
      $('#getAllUsers').html(data);
      $('#getAllUsers2').html(data);
    },
    error: err => {
      //$('#getAllUsers').html("<option>test</option>");
      //$('#getAllUsers2').html("<option>test</option>");
    },
    complete: () => {
      // Schedule the next request when the current one's complete
      setTimeout(getAllUsers, 5000);
    }
  });
}
getAllUsers();  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="select2" name="user" id="getAllUsers" required>
  <option selected="true" disabled="disabled">Loading Users...</option>
</select>

<select class="select2" name="user" id="getAllUsers2" required>
  <option selected="true" disabled="disabled">Loading Users...</option>
</select>  

Комментарии:

1. Спасибо! Это устранило мою проблему.

2. Рад помочь, glhf 🙂

Ответ №2:

Сначала вам нужно понять, почему у вас это не работает, а затем найти решение.

Проблема в том, что вы используете один и тот же идентификатор элемента в двух отдельных элементах, это строго не запрещено и не вызовет у вас никаких ошибок, но это указывает на неправильную реализацию.

Когда вы пытаетесь выбрать элементы с идентификатором getAllUsers с помощью jQuery, он знает, что должен быть только один такой элемент, поэтому выбирает только первый. Любые другие элементы с таким же идентификатором игнорируются. Вот почему это сработало только для первого.

Теперь давайте попробуем найти решения.

Одно решение, предложенное Мирославом Гламузиной, правильное и работающее, но недостаточно гибкое.

Другим решением было бы использовать селектор, который выбирает несколько элементов, которые не являются идентификаторами. Лучший вариант — использовать класс элемента, который будет уникальным для ваших двух (или более) select элементов. Итак, если вы хотите добавить еще одну в будущем, вам не нужно прикасаться к JS-коду, а только к HTML-части.

Вы можете сделать что-то вроде этого:

HTML

 <select class="select2 getAllUsers" name="user" required>
    <option selected="true" disabled="disabled">Loading Users...</option>
</select>

<select class="select2 getAllUsers" name="user2" required>
    <option selected="true" disabled="disabled">Loading Users...</option>
</select>
  

(Обратите внимание, что я также изменил name атрибут второго select , чтобы предотвратить проблемы в будущем)

JavaScript

 (function getAllUsers() {
    $.ajax({
        url: 'staff/getAllUsers.php',
        success: function(data) {
            $('.getAllUsers').html(data);
        },
        complete: function() {
            // Schedule the next request when the current one's complete
            setTimeout(getAllUsers, 5000);
        }
    });
}());
  

ВНИМАНИЕ!
Если вы планируете использовать этот скрипт публично, вам следует обратить внимание на проблему безопасности в этом скрипте.

Этот скрипт открыт для XSS-атак. Потому что вы запрашиваете удаленный контент и применяете его содержимое как HTML без каких-либо проверок данных или экранирования.

Я бы предложил в вашем случае сгенерировать JSON в PHP-скрипте со списком пользователей и всеми необходимыми данными, затем в JavaScript создать option элементы, используя данные из списка JSON.

Вы должны сделать что-то вроде этого:

Допустим, что это JSON, полученный от staff/getAllUsers.php :

 [
    {"id": 14, "name": "User 1"},
    {"id": 16, "name": "User 2"},
    {"id": 17, "name": "User 3"}
]
  

JavaScript:

 (function getAllUsers() {
    $.ajax({
        url: 'staff/getAllUsers.php',
        success: function(data) {
            try {
                const list = JSON.parse(data); // Parse JSON from string to object
                const selectEl = $('.getAllUsers').empty(); // Clear the content of both `select` elements
                for ( let i=0; i<list.length; i   ) { // Loop through each item in the JSON array
                    $('<option />') // Create an `option` element
                        .attr('value', list[i].id) // Set attribute `value` to `option` element
                        .text(list[i].name) // Set `option` text (this function also escapes any special characters, which prevents potential XSS attacks)
                        .appendTo(selectEl); // Add `option` element to both `select` elements
                }
            } catch (e) {
                // Report any errors with the JSON parsing process to the developer console.
                console.error(e);
            }
        },
        error: function(jqXHR, textStatus, errorThrown) {
            // Track any errors received from the server for debugging purposes
            console.error(textStatus, errorThrown);
        }
        complete: function() {
            // Schedule the next request when the current one's complete
            setTimeout(getAllUsers, 5000);
        },
        dataType: 'json' // Expect a `json` back from server
    });
}());
  

Я надеюсь, вы сможете чему-то научиться из этого.
Удачи!