Как передать имя объекта в обещание JavaScript, которое ожидает, пока объект не будет инициирован?

#javascript

Вопрос:

Мне нужна функция, которая разрешает обещание JavaScript, как только объект определен.

Я разработчик плагинов WordPress, и я сталкиваюсь с проблемой, что я не могу контролировать, где мой код размещается на веб-сайте (некоторые сторонние плагины для «оптимизации» JavaScript даже могут перемешивать код). И у меня нет контроля над объектами, которые я пытаюсь проверить. В примере jQuery мой код может быть размещен выше или ниже jQuery, и мой код зависит от jQuery .

Я представляю себе следующее:

 function objectExists(object) {
    return new Promise(function (resolve, reject) {
        (function waitForObject() {
            if (object) return resolve();
            setTimeout(waitForObject, 30);
        })();
    });
}


objectExists(jQuery).then(function () {
  // run my code
}
 

Проблема в том , что браузер выдаст ошибку в строке objectExists(jQuery).then(function () { , сообщив, что jQuery она не определена.

Когда я пишу обещание проверять только jQuery то, работает ли оно.

 function jQueryExists() {
    return new Promise(function (resolve, reject) {
        (function waitForJQuery() {
            if (jQuery) return resolve();
            setTimeout(waitForJQuery, 30);
        })();
    });
}
 

Но я хочу иметь возможность передать функции любое имя объекта до того, как этот объект будет определен. Как мне это сделать?

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

1. Действительно маловероятно, что это лучшее решение вашей проблемы. Почти никогда не рекомендуется «опрашивать» о каком-либо побочном эффекте в вашем коде, когда вы можете просто использовать обработчики событий для прослушивания фактического состояния.

2. » Мне нужна функция, которая разрешает обещание JavaScript, как только объект определен». — затем создайте обещание и разрешите его из кода, определяющего объект . Не проверяйте повторно, определено оно или нет.

3. @meagar Я разработчик плагинов WordPress, и я сталкиваюсь с проблемой, что я не могу контролировать, где мой код размещается на веб-сайте. В примере jQuery мой код может быть размещен выше или ниже jQuery, и мой код зависит от jQuery. Я также не люблю проводить опросы. Но я не знаком с концепцией, о которой вы говорите. Не могли бы вы, пожалуйста, указать мне на возможное решение с помощью обработчиков событий?

4. @Bergi: Но у меня нет контроля над этим сторонним кодом, например jQuery . Поэтому я не могу «разрешить это из кода, определяющего объект». Или я вас неправильно понял?

5. @alev Наверняка в wordpress скрипт может объявить jQuery своей зависимостью — по крайней мере, это то, что я нашел за 1 минуту поиска в Google

Ответ №1:

Если объект будет глобальным, передайте строку и используйте typeof вместо нее, которая будет работать для переменных, которые еще не были определены:

 function objectExists(varName) {
    return new Promise(function (resolve, reject) {
        (function waitForObject() {
            if (typeof window[varName] !== 'undefined') return resolve();
            setTimeout(waitForObject, 30);
        })();
    });
}


objectExists('jQuery').then(function () {
  // run my code
});
 

(или вы можете использовать существующий код window.jQuery вместо этого — ссылка на несуществующее свойство объекта не приведет к ошибке)

Но это действительно странная вещь, которую хочется сделать. Лучше прикрепить load прослушиватель к <script> тегу jQuery.

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

1. Спасибо. Но я не могу «прикрепить прослушиватель загрузки к тегу jQuery <script>», потому что у меня нет контроля над теми объектами и сценариями, о которых я говорил. Мне следовало бы лучше уточнить это в своем вопросе. Теперь я добавил больше контекста.

2. Замечательный. Предлагаемое решение работает! Попытка window.jQuery не приводит к ошибке (как вы предположили), но по какой-то причине никогда не решает обещание.