Я пишу простую функцию в JavaScript:
function waitThenRun(objectToWaitFor, callback) {
// logic to periodically check for objectToWaitFor to become something
// then call the callback
}
И я намерен использовать его как:
waitThenRun(someObjectThatWillBeDefinedLater, function() {
// Doing something with someObjectThatWillBeDefinedLater
});
Тем не менее, я получаю эту ошибку:
Uncaught ReferenceError: someObjectThatWillBeDefinedLater is not defined
Как вы справляетесь с этим?
Проще говоря, я хочу запускать фрагмент кода только тогда, когда определена глобальная переменная JSON, и я не могу определить, когда и где она определяется. Иногда он определяется после моего кода, иногда перед моим кодом, иногда на секунду позже, иногда на 5 секунд позже. Это недетерминировано.
Я имею в виду, что мой код может выполняться до его определения или после его определения. Это недетерминировано.
Переменные передаются по значению, а не по ссылке. Функция не может проверить, определена ли переменная в области действия вызывающего объекта.
@Barmar, тогда как убедиться, что он определен? Это чем-то похоже на jQuery $(document).ready(), но для глобального объекта JSON.
Вы боретесь против того, как все делается в javascript. Обычно можно использовать обратный вызов или прослушиватель событий, чтобы узнать, когда что-то произошло. У вас есть код, который определяет переменную — вы должны вызвать свою функцию или обратный вызов там (так работает $(document).ready() — он принимает обратный вызов). Все остальное с таймерами и опросом будет халтурой.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если это глобальная переменная, вы можете передать имя переменной в виде строки. Поскольку глобальные переменные становятся свойствами объекта window, функция может проверить, определен ли window[objectToWaitFor].
function waitThenRun(objectToWaitFor, callback) {
var interval = setInterval(function() {
if (window[objectToWaitFor] !== undefined) {
clearInterval(interval);
callback();
}
}
}
waitThenRun("someObjectThatWillBeDefinedLater", function() {
// do something with someObjectThatWillBeDefinedLater
});
вы можете сделать это, используя
var checkExist = setInterval(function() {
if (JsonObject) {
//execute your method here
console.info("Exists!");
clearInterval(checkExist);
}
}, 100); // check every 100ms
Вы сами пробовали? Это if (JsonObject) именно там, где я получаю ошибку. Вот почему я задал этот вопрос.
Все глобальные переменные присоединены к объекту window, поэтому вы можете передать имя переменной вашей функции в виде строки и проверить, существует ли она в window, а затем запустить обратный вызов, если он есть. Фрагмент:
setTimeout(function() {
window.someObjectThatWillBeDefinedLater = {hello: 'world'};
}, 1000);
function waitThenRun(globalObj, callback) {
let intervalId = setInterval(function() {
if (window[globalObj] !== undefined) {
callback(window[globalObj]);
clearInterval(intervalId);
}
}, 200);
}
waitThenRun('someObjectThatWillBeDefinedLater', console.info.bind(console));Вы можете попробовать использовать метапрограммирование, такое как прокси-серверы JS, для перехвата метода set свойства объектов. Что-то вроде этого:
function tracePropAccess(obj, propKeys) {
const propKeySet = new Set(propKeys);
return new Proxy(obj, {
get(target, propKey, receiver) {
if (propKeySet.has(propKey)) {
console.info('GET '+propKey);
}
return Reflect.get(target, propKey, receiver);
},
set(target, propKey, value, receiver) {
if (propKeySet.has(propKey)) {
console.info('SET '+propKey+'='+value);
}
return Reflect.set(target, propKey, value, receiver);
},
});
}
фрагмент был взят из здесь
В вашем примере, когда вызывается свойство set, вы можете проверить, соответствует ли значение ожидаемому значению, и сделать с ним все, что хотите.
Вы можете отправить событие в window, когда вы определяете свой объект JSON и добавляете прослушиватель событий для этого события в окно. Таким образом, вам не нужно будет использовать setInterval, чтобы постоянно проверять, определена ли глобальная переменная.
function defineJSON(){
window.JSONObj = {x: "something"};
triggerEvent("JSONDefined", window, {JSONObjName: "JSONObj"});//fire a custom event on the window when you define the JSON Object
}
function triggerEvent(type, obj, data){
var ev;
if (document.createEvent) {
ev = document.createEvent("HTMLEvents");
ev.initEvent(type, true, true);
} else {
ev = document.createEventObject();
ev.eventType = type;
}
ev.eventName = type;
if (data){
for(var key in data){
if (data.hasOwnProperty(key)){
ev[key] = data[key];
}
}
}
if (document.createEvent) {
obj.dispatchEvent(ev);
} else {
obj.fireEvent("on" + ev.eventType, ev);//for < IE8
}
}
window.addEventListener("JSONDefined", function(ev){
//this event handler will be called when the JSON Object is defined
console.info("JSON defined:", window[ev.JSONObjName]);
});
setTimeout(function(){
defineJSON();
}, 2000);//define JSON Object after 2 seconds (just for this example)
Что ты имеешь в виду
and I can't determine when it gets defined? Разве это не определено где-то в вашем коде?