监听 JavaScript 变量的变化

7

假设有一段代码在第2个位置

var place2IsReady = true;

位置1,我需要实现以下逻辑:
Once place2IsReady value was changed (to true) then display alert('ready!');

备注:

  • place2IsReady 变量在 场所1 的范围内不可用。
  • 场所1 中的代码在 场所2 执行之前就被执行了(或存在竞争条件)。

解决方法1

我相信我可以使用 window.place2IsReady,并在场所1使用 setTimeout/setInterval 直到我得到 window.place2IsReady === true

有更好的选择吗?使用监听器?在变量更改时进行操作?

P.S. 我只需要追踪 place2IsReady 的第一个可能的更改。

有更好的方式吗?谢谢。


你在使用一些框架吗? - distante
变量在更改时不会发出任何通知。您必须不断轮询并检查变量是否更改,或者实际上使用一些模式或库来跟踪更改。 - VLAZ
1
@distante 我的首选答案:不。在一些地方使用 JS + TS + jQuery。但最好采用原生 JS 解决方案。 - Haradzieniec
“place2IsReady”可以是一个对象而不是布尔值吗? - AndAC
不确定您具体需要什么,但是您可以使用 https://javascript.info/property-accessors 中的 getter/setter,在 setter 调用执行时进行相关操作。 - Maulik
2个回答

4
您可以使用setTimeout创建变量更改的监听器,类似于以下内容:

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();
}

一个更通用的监听器“工厂”可能是:

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);
}

你或许可以使用代理对象(Proxy),并结合set trap来实现。

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);


谢谢。您能解释一下为什么place2IsReady = true; place2IsReady = false; place2IsReady = true;不会显示第二个警报吗? - Haradzieniec
如果我理解你的意思,我可以这样做。 - KooiInc
@Kooilnc,明白了,谢谢,它只执行了一次。 - Haradzieniec

1
假设您可以用一个对象替换place2IsReady:
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接