How do you make an event listener that detects if a boolean variable becomes true?

荒凉一梦 提交于 2019-11-30 14:06:50

问题


For example, I have var menu_ready = false;. I have an ajax function that sets menu_ready to true when the ajax stuff is done:

//set up event listener here

$(...).load(..., function() {
    ...
    menu_ready = true;
}

How do I set up an event listener that waits for menu_ready to be true?


回答1:


One way is continual polling:

function checkMenu() {
    if (!menu_ready) {
        setTimeout("checkMenu();", 1000);
        return;
    } else {
        // menu_ready is true, so do what you need to do here.
    }
}

and...

<body onload="checkMenu();">



回答2:


You can't attach event listeners to JavaScript variables per se, but you can fake it. Instead of a boolean var, use an object with get, set, and listen methods:

function Bool(initialValue) {
    var bool = !!initialValue;
    var listeners = [];
    var returnVal = function(value) {
        if (arguments.length) {
            var oldValue = bool;
            bool = !!value;
            listeners.forEach(function (listener, i, list) {
                listener.call(returnVal, { oldValue: oldValue, newValue: bool });
            });
        }
        return bool
    };
    returnVal.addListener = function(fn) {
        if (typeof fn == "function") {
            listeners.push(fn);
        }
        else {
            throw "Not a function!";
        }
    };
    return returnVal;
}

You'd use it like this:

var menu_ready = Bool(false);
if (menu_ready()) {
    // this code won't get executed, because menu_ready() will currently return false;
}
menu_ready.addListener(function (e) {
    if (e.oldValue != e.newValue) {
        // value changed!
    }
});
menu_ready(true);  // listeners are called.



回答3:


There is no cross-browser (cross-platform) event which gets that job done. There are some pretty specific mechanisms to watch objects propertys for instance, but nothing to watch out for booleans (imo).

You want to execute a callback function aswell at the time you're setting that variable to true. You can also apply some jQuery sugar:

function myCallbackReference() {
    alert('yay');
}

$('#foobar').load('/some/code', function() {
    menu_ready = true;
}).done( myCallbackReference );



回答4:


Why do not create a function menuReady that will be fired when you want ?

menuReady();



回答5:


function menuReady(){
  // Do whatever it is you need done when menu is ready
}    

$(...).load(..., function() {
  menuReady();// menuReady is called on callback    
});



回答6:


Since this is a pretty old question and many of these answers are out of date, I thought I'd add a more current answer.

Background

Javascript is an event driven language. So, any change that occurs in the environment at any time other than when the page is first loaded is caused by some sort of event. As such, the best way to communicate changes is to use events. You either listen for the same event that caused the change you want to watch or you create a new event to let people know when something specifically has changed.

Node.js has an eventEmitter object that is very useful and is pure Javascript (no DOM involved). That same code can also be used in the browser if one wants a general purpose event mechanism that is independent of the DOM.

The browser DOM has it's own event notification system where you can create events, trigger events and listen for events.

Polling for changes (as the accepted answer here shows) is generally a "hack" that is inefficient, can miss changes, is not necessarily timely, wastes battery and CPU, etc... If you control the code, there is always a better way to design it than polling.

The OP's Actual Problem

There still is not efficient mechanism of monitoring a variable change, but the OP's problem was actually that someone wants to know when this code gets triggered:

$(...).load(..., function() {
    ...
    menu_ready = true;
}

Of course, one simple answer is that anyone who wants to know when that is ready could also just monitor the same thing this is with $(...).load(), but that would somewhat tie their notification to how this was specifically implemented.

Creating Our Own Event Notification That Anyone Can Listen For

Instead, what would be better would be to create our own event and when we know the menu is ready, we trigger that event. Then anyone, anywhere in the code can listen for that same event.

The browser already has an extensible event system built in as described here. So, we can use that here. You need to pick some well-known object to trigger the event on that exists at the time any listener would want to register to know about this. Since the OP didn't show any specific context, I'll just pick the window object.

$(...).load(..., function() {
    ...
    menu_ready = true;

    // create new event
    var event = new Event('menu_ready');

    // Dispatch the event.
    window.dispatchEvent(event);        
 }

Note, you can use any DOM object as the source of the event (whatever makes the most sense for your application) as long as it exists at both the time someone wants to register for the event and the time at which the event occurs.

Then, a listener anywhere in your code can listen for this event:

 window.addEventListener("menu_ready", function() {
     console.log("menu is now ready");
 });

Working Demo

Here's an actual working implementation that triggers the event upon a button press.

let button = document.getElementById("pressme");

button.addEventListener("click", function() {
    // create new event
    var event = new Event('menu_ready');

    // Dispatch the event.
    window.dispatchEvent(event);        

});

function log(x) {
    var div = document.createElement("div");
    div.innerHTML = x;
    document.getElementById("log").appendChild(div);
}


// then create a listener
window.addEventListener("menu_ready", function() {
    log("Got menu_ready event");
});
#log {margin-top: 50px;}
<button id="pressme">
Press Me
</button>
<div id="log">

</div>

I crafted this answer to match the original problem illustrated in the question here. For reference, there are several other useful mechanisms of seeing changes, but they generally rely on properties of an object, not just a simple variable.

See all the answers on this question: Listening for variable changes. But specifically make sure you read these two:

Using a proxy object to track changes

Using getters and setters to track changes




回答7:


Utils = {
    eventRegister_globalVariable : function(variableName,handlers){
        eventRegister_JsonVariable(this,variableName,handlers);
    },
    eventRegister_jsonVariable : function(jsonObj,variableName,handlers){
        if(jsonObj.eventRegisteredVariable === undefined) {
            jsonObj.eventRegisteredVariable={};//this Object is used for trigger event in javascript variable value changes ku
        }
        Object.defineProperty(jsonObj, variableName , {
                    get: function() { 
                        return jsonObj.eventRegisteredVariable[variableName] },
                    set: function(value) {
                        jsonObj.eventRegisteredVariable[variableName] = value; handlers(jsonObj.eventRegisteredVariable[variableName]);}
                    });
            }


来源:https://stackoverflow.com/questions/6783876/how-do-you-make-an-event-listener-that-detects-if-a-boolean-variable-becomes-tru

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!