3

I'm writing a simple function in JavaScript:

function waitThenRun(objectToWaitFor, callback) {
   // logic to periodically check for objectToWaitFor to become something
   // then call the callback
}

And I intend to use it as:

waitThenRun(someObjectThatWillBeDefinedLater, function() {
    // Doing something with someObjectThatWillBeDefinedLater
});

Yet I get this error:

Uncaught ReferenceError: someObjectThatWillBeDefinedLater is not defined

How do you handle this?

In simpler terms, I want to run a piece of code only when a global JSON variable is defined, and I can't determine when and where it gets defined. Sometimes it gets defined after my code, sometimes before my code, sometimes a second later, sometimes 5 seconds later. It's non-deterministic.

5
  • What do you mean you and I can't determine when it gets defined? Isn't it defined somewhere in your code? Commented Mar 9, 2019 at 20:02
  • I mean my code might run before its definition, or after its definition. It's non-deterministic. Commented Mar 9, 2019 at 20:05
  • Variables are passed by value, not by reference. There's no way for a function to test whether the variable is defined in the caller's scope. Commented Mar 9, 2019 at 20:05
  • @Barmar, then how do you make sure it's defined? It's somehow similar to jQuery's $(document).ready(), but for global JSON object. Commented Mar 9, 2019 at 20:08
  • You are fighting against the way things are done in javascript. Usually one would use a callback or an event listener to know when something has happened. You have code that is defining the variable — you should call your function or a callback there (this is how $(document).ready() works -- it takes a callback). Everything else with timers and polling will be a hack. Commented Mar 9, 2019 at 20:20

5 Answers 5

2

You can dispatch an event on the window when you define your JSON Object and add an event listener for that event on the window. This way, you will not need to use a setInterval to continuously check if a global variable is defined.

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.log("JSON defined:", window[ev.JSONObjName]);
});
setTimeout(function(){
   defineJSON();
}, 2000);//define JSON Object after 2 seconds (just for this example)

Sign up to request clarification or add additional context in comments.

Comments

0

If it's a global variable, you can pass the variable name as a string. Since global variables become properties of the window object, the function can then check whether window[objectToWaitFor] is defined.

function waitThenRun(objectToWaitFor, callback) {
    var interval = setInterval(function() {
        if (window[objectToWaitFor] !== undefined) {
            clearInterval(interval);
            callback();
        }
    }            
}

waitThenRun("someObjectThatWillBeDefinedLater", function() {
    // do something with someObjectThatWillBeDefinedLater
});

Comments

0

All global variables are attached to the window object so can pass the variable name to your function as a string and check if it exists on the window and then run your callback if it does. Snippet:

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.log.bind(console));

Comments

0

you can do this by using

   var checkExist = setInterval(function() {
   if (JsonObject) {
//execute your method here
      console.log("Exists!");
      clearInterval(checkExist);
   }
}, 100); // check every 100ms

1 Comment

Have you tried it yourself? That if (JsonObject) is exactly where I get error. That's why I asked this question.
0

You can try to use metaprogramming like JS proxies to intercept the set method of an objects property. Something like this:

function tracePropAccess(obj, propKeys) {
    const propKeySet = new Set(propKeys);
    return new Proxy(obj, {
        get(target, propKey, receiver) {
            if (propKeySet.has(propKey)) {
                console.log('GET '+propKey);
            }
            return Reflect.get(target, propKey, receiver);
        },
        set(target, propKey, value, receiver) {
            if (propKeySet.has(propKey)) {
                console.log('SET '+propKey+'='+value);
            }
            return Reflect.set(target, propKey, value, receiver);
        },
    });
}

the snippet was taken from here

In your example, when the set property gets called you can check if the value meets your expected value and do as you wish with it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.