Haradzieniec
Haradzieniec

Reputation: 9338

Listen to js variable change

Let's say there is a code in place 2

var place2IsReady = true;

In place 1 I need to implement the logic below :

Once place2IsReady value was changed (to true) then display alert('ready!');

Notes:

Solution 1

I believe I can use window.place2IsReady instead and use setTimeout/setInterval in place 1 until I get window.place2IsReady === true.

Any better options? Using Listeners? On the variable change?

P.S. I need to track only first possible change of place2IsReady.

Is there a better way? Thank you.

Upvotes: 8

Views: 13978

Answers (2)

AndAC
AndAC

Reputation: 246

Assuming you can replace place2IsReady with an object:

place2IsReady = {
  state: false,
  set ready(value) {
      this.state = value
      state && place_1_call()
  },
  get ready() { 
    return state
  }
}

place_1_call = () => {
  alert('ready')
}

place2IsReady.ready = true

Upvotes: 1

KooiInc
KooiInc

Reputation: 122936

You can create a listener for the variable change using setTimeout, something like:

let place2IsReady = false;

setReadyListener();

// testing wait 2 seconds to set place2IsReady to true
// so: an alert should occur after 2 seconds
setTimeout(() => place2IsReady = true, 2000);

function setReadyListener() {
  const readyListener = () => {
    if (place2IsReady) {
      return alert("Ready!");
    }
    return setTimeout(readyListener, 250);
  };
  readyListener();
}

A more generic listener 'factory' could be:

let place2IsReady = false;
let fromObj = {
  place2IsReady: "busy",
  done() { this.place2IsReady = "done"; },
};
const listen = changeListenerFactory();

listen(
  () => place2IsReady, 
  () => console.log("place2IsReady") );
listen(
  () => fromObj.place2IsReady === "done", 
  () => console.log("formObj.place2IsReady done!") );
  
console.log("Listening...");

// test change variables with listeners
setTimeout(() => place2IsReady = true, 1000);
setTimeout(() => fromObj.done(), 3000);

function changeListenerFactory() {
  const readyListener = (condition, callback, delay) => {
    if (!condition || typeof condition !== "function") { return true; }
    if (condition()) {
      return callback();
    }
    setTimeout(() => readyListener(condition, callback, delay), delay);
  };
  
  return (condition, callback = () => {}, delay = 250) => 
    readyListener(condition, callback, delay);
}

Or maybe using a Proxy (with a set trap) works for you

const readyState = new Proxy({ ready: false }, { 
  set (target, prop, val) {
    console.log(`readyState.ready changed from ${target[prop]} to ${val}`);
    target[prop] = val;
  }
});

console.log("Waiting for changes ...");
setTimeout(() => readyState.ready = true, 2000);

Upvotes: 5

Related Questions