簡體   English   中英

等待一個變量存在,然后在 javascript 中做一些事情

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM