[英]Wait for a variable to exist then do something in javascript
我有一個腳本,它將在加載必須讀取的變量之前執行..
這是我將首先執行的腳本
funcThatWaits(varToWait).ready(function(){
//callback time!!
alert("varToBeWait is Ready!!");
});
這是接下來要加載的腳本
var varToWait=null;
我想要的只是創建一個函數,該函數將等待變量存在並在檢測到變量已存在時自動執行回調。(這意味着當變量不存在時,它將等待)
這可能嗎? 我的第一個腳本完全復制在 jquery 的 $(document).ready() 函數上,它等待 DOM 完全加載......這可能用於 JS 變量嗎?
如果您的變量來自另一個函數(可能來自另一個作用域),那么您可以傳遞一個回調,並在第二個函數執行該回調時向其提供變量。 您無需等待它存在的時間,但是您將等到第二個腳本為您提供它 。
//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
})
}
另一種方法是預先定義一個加載程序腳本,以聚合回調並在設置了變量后調用它們:
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);
我發現的唯一方法是創建一個成熟的跟蹤機制。
當前接受的答案可以完成這項工作,但我個人更喜歡隱藏實現細節。
我們將創建一個類來跟蹤事物。
/* 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);
}
}
}
我們將裝載一艘宇宙飛船。 它最終會擁有我們的變量,但它是異步的並且需要很長時間來初始化。
/* 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);
以下腳本需要該變量。 它會要求它,並在第一次設置時繼續。 請注意,運行順序無關緊要 - 無論此代碼先運行還是飛船先加載,這都將起作用。
/* 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' }
});
如果您只關心獲取當前值,則上述方法可以正常工作。 下面我們有一個記錄器,它將跟蹤所有未來的變化:
/* 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' }
});
每次設置值時,上面的類都會通知所有getEveryChange
偵聽器,即使它與以前的值完全相同。 如果這不是你想要的,你可以通過添加if (this._value === value) return;
來防止這種行為if (this._value === value) return;
到setValue
類方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.