[英]Wait for a variable to exist then do something in javascript
I have a script that will be executed before the variable it must read will be loaded..我有一个脚本,它将在加载必须读取的变量之前执行..
this is my script that will be executed first这是我将首先执行的脚本
funcThatWaits(varToWait).ready(function(){
//callback time!!
alert("varToBeWait is Ready!!");
});
and this is the script that will be next to be loaded这是接下来要加载的脚本
var varToWait=null;
All I want is to create a function that will wait to a variable to exist and do a callback automatically when it detects the variable already existed.(This means while the variable does not exist it will wait)我想要的只是创建一个函数,该函数将等待变量存在并在检测到变量已存在时自动执行回调。(这意味着当变量不存在时,它将等待)
Is this possible?这可能吗? my first script is quite copied on the $(document).ready() function of jquery that waits for the DOM to be fully loaded... is this possible for JS variables?我的第一个脚本完全复制在 jquery 的 $(document).ready() 函数上,它等待 DOM 完全加载......这可能用于 JS 变量吗?
If your variable comes from another function (and maybe from another scope), then you can pass a callback and provide it the variable when the second function executes the callback. 如果您的变量来自另一个函数(可能来自另一个作用域),那么您可以传递一个回调,并在第二个函数执行该回调时向其提供变量。 you don't need to wait when it will exist, but you will wait until the second script provides it for you . 您无需等待它存在的时间,但是您将等到第二个脚本为您提供它 。
//in the second script:
var varIWant = 'foo'
function fromSecondScript(callback){
callback(varIWant);
}
//in the first script:
function fromFirstScript(){
fromSecondScript(function(theVar){
//"theVar" in this function scope is "varIWant" from the other scope
})
}
another way to do it is to have a loader script defined beforehand to aggregate callbacks and call them once their variables are set: 另一种方法是预先定义一个加载程序脚本,以聚合回调并在设置了变量后调用它们:
var aggregator = (function(){
var stored = {};
return {
//adds a callback to storage
addCallback : function(varName,callback){
if(!stored.hasOwnProperty(varName)){
stored[varName] = [];
}
stored[varName].push(callback);
},
//executes stored callbacks providing them data
execute : function(varName,data){
if(stored.hasOwnProperty(varName)){
for(var i=0;i<stored[varName].length;i++){
stored[varName][i](data)
}
}
}
}());
//in the first script add callbacks. you can add any number of callbacks
aggregator.addCallback('VarExists',function(theVar){
//do what you want when it exists
});
aggregator.addCallback('VarExists',function(theVar){
//another callback to execute when var exists
});
//in the second script, execute the callbacks of the given name
aggregator.execute('VarExists',theVarYouWantToShare);
The only way I've found is to create a fully-fledged tracking mechanism.我发现的唯一方法是创建一个成熟的跟踪机制。
The currently accepted answer does the job, but I personally like to hide implementation details a bit more.当前接受的答案可以完成这项工作,但我个人更喜欢隐藏实现细节。
We'll create a class to keep track of things.我们将创建一个类来跟踪事物。
/* ChangeTracker.js */
// Mechanism to keep track of when a variable is set.
class ChangeTracker {
constructor() {
this._value = null; // <- the var we're waiting for
this._valueAlreadySet = false; // <- used to track first set
this._singleListeners = []; // <- used for one-off requests
this._multiListeners = []; // <- used for recurring requests
}
// Using this, you'll be notified the first time the value changes. If the
// value has already been set, you'll be notified immediately.
getOnce(callback) {
if (this._valueAlreadySet) {
callback(this._value);
}
else {
this._singleListeners.push(callback);
}
}
// Using this, you'll be notified every time the value changes. If the value
// has already been set, you'll be notified immediately.
getEveryChange(callback) {
this._multiListeners.push(callback);
if (this._valueAlreadySet) {
callback(this._value);
}
}
// Sets the value, then notifies those waiting for it.
setValue(value) {
this._value = value;
if (!this._valueAlreadySet) {
this._valueAlreadySet = true;
// Notify all one-off listeners.
const singleListeners = this._singleListeners;
for (let i = 0; i < singleListeners.length; i++) {
singleListeners[i](value);
}
// Mark for garbage collection.
this._singleListeners = null;
}
// Notify all subscribers.
for (let i = 0; i < this._multiListeners.length; i++) {
this._multiListeners[i](value);
}
}
}
We'll be loading a spaceship.我们将装载一艘宇宙飞船。 It will eventually have our variable, but it's asynchronous and takes long to initialise.它最终会拥有我们的变量,但它是异步的并且需要很长时间来初始化。
/* shipLoader.js */
// We will store a 1GB spaceship in here.
const spaceship = new ChangeTracker();
// Simulate a long loading process:
setTimeout(() => {
spaceship.setValue({ name: 'Friday', color: 'Lilac' });
}, 6174);
// Player gets into a bigger spaceship:
setTimeout(() => {
spaceship.setValue({ name: 'The Unshakeable', color: 'Blood red' });
}, 9999);
The following script wants the variable.以下脚本需要该变量。 It'll ask for it, and proceed the first time that it's set.它会要求它,并在第一次设置时继续。 Note that run order does not matter - this will work whether this code runs first or the spacehip loads first.请注意,运行顺序无关紧要 - 无论此代码先运行还是飞船先加载,这都将起作用。
/* activateHud.js */
// Receive the value when it's set, then do some processing.
spaceship.getOnce((value) => {
console.log('Got spaceship:', value);
// ^-> Got spaceship: { name: 'Friday', color: 'Lilac' }
});
The above works fine if you care only about getting the current value.如果您只关心获取当前值,则上述方法可以正常工作。 Below we have a logger that will keep track of all future changes:下面我们有一个记录器,它将跟踪所有未来的变化:
/* logger.js */
// Log the value every time it changes.
spaceship.getEveryChange((value) => {
const date = new Date().toLocaleString();
console.log(`[${date}] New spaceship loaded:`, value);
// ^-> New spaceship loaded: { name: 'Friday', color: 'Lilac' }
// > New spaceship loaded: { name: 'The Unshakeable', color: 'Blood red' }
});
The above class will notify all getEveryChange
listeners every time you set the value, even if it's the exact same value as before.每次设置值时,上面的类都会通知所有getEveryChange
侦听器,即使它与以前的值完全相同。 If this is not desired, you can prevent this behaviour by adding if (this._value === value) return;
如果这不是你想要的,你可以通过添加if (this._value === value) return;
来防止这种行为if (this._value === value) return;
to the setValue
class method.到setValue
类方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.