Подключение callback-функции из другого js-файла

412
12 декабря 2016, 10:03

Приветствую.

Есть 1-й js-файл со следующим кодом:

(function($) {
$(function() {
    function myfunction(callback) {
        // тут jQuery-код
        callback();
    }
    myfunction(showAlert);
});
})(jQuery);

Есть 2-й js-файл со следующим кодом:

(function($) {
$(function() {
    function showAlert() {
        alert('Hello!');
    }
});
})(jQuery);

Вопросы:

  1. Как сделать, чтобы функция showAlert() запускалась из 2-го файла? Сейчас выдается ошибка: `Uncaught ReferenceError: showAlert is not defined.

  2. Как сделать, чтобы ошибки Uncaught ReferenceError: showAlert is not defined также не было в том случае, когда нет второго js-файл (т.е. когда функция showAlert() нигде не прописана)?

Т.е. по сути мне нужна возможность запуска callback-функции из любого другого js-файла, подключенного к сайту.

Answer 1

Для решения проблемы номер 1 надо функцию положить в глобальный объект. Например, так:

window.showAlert = function() {
    alert('Hello!');
};

Такой подход допустим, если ваш модуль экспортирует всего одну функцию. Иначе лучше экспортировать один объект, в котором будет лежать все остальное:

window.Module2 = {
    showAlert : function() {
        alert('Hello!');
    },
};

Теперь по пункту 2. В принципе, можно сделать как-то вот так:

Module2 && Module2.showAlert();

Иными словами, проверяем существование и вызываем при наличии. Если такой вариант не понятен, то можно использовать вот этот:

if (Module2) {
    Module2.showAlert();
}

Но первый вариант заметно короче и удобней. Советую все-таки использовать его - в javascript это довольно популярный трюк для работы с элементами, которых может не быть.

Но скажите, почему вообще допустима ситуация, когда чего-то важного для выполнения кода на странице не оказывается? Вероятнее всего, проблема на самом деле архитектурная. Код, в котором слишком много подобных конструкций, называется макаронным. Рекомендую почитать про шаблоны проектирования, позволяющие уменьшить связность кода.

К примеру, тут мог бы помочь паттерн "Публикация/подписка".

Answer 2

Вы нарушаете законы области видимости. Помещая что-то в самовызываюшуюся функцию (function() {})() вы создаете новую область видимости. Области идут сверху в низ, но не с низу вверх. Поэтому ваша функция видит,все что находится на уровень выше, но вот этот уровень выше в ф-цию заглянуть не сможет. От сюда и ошибка, что ваш callback не определен. Вашу проблему не решить, не вынося хоть-что в глобальную область видимости.
Что бы проверить можно ли вызывать функцию, можно сделать так:

func && typeof func == 'function' && func()

Не совсем явно, поэтому расскажу:

  1. Проверяем, определенна ли переменная ( в данном случае undefined она или нет)
  2. Проверяем является ли переменная функцией
  3. Выполняем функцию ( в js ленивая логика, если где-то запнется перед последней проверкой, дальше даже не пойдет )

На счет главного вопроса: либо создайте один глобальный модуль, аля Callbacks, там записывайте все колбеки ( доступ только через объект Callbacks)

var Callback = {}
Callback.showAlert = function () {};
showAlert() // ошибка
Callback.showAlert() // все работает

Либо выносите переменные в глобальную область видимости ( либо под одну самовызываюшуюся ф-цию)

Answer 3

Поместите её вне блока function($){}. Тогда она будет глобальной.

READ ALSO
Убрать запятую в конце массива

Убрать запятую в конце массива

Вывожу данные из массиваПри выводе последней строки нужно убрать запятую и пробел (

506
Скролл с конца div

Скролл с конца div

Добрый день!

272