Javascript 如何使事件侦听器检测布尔变量是否为真?

Javascript 如何使事件侦听器检测布尔变量是否为真?,javascript,events,event-handling,jquery,Javascript,Events,Event Handling,Jquery,例如,我有var菜单\u ready=false。我有一个ajax函数,当ajax工作完成时,它会将菜单\u ready设置为true: //set up event listener here $(...).load(..., function() { ... menu_ready = true; } 如何设置事件侦听器以等待菜单\u ready为真?没有跨浏览器(跨平台)事件可以完成该任务。例如,对于对象属性有一些非常特定的机制,但是没有什么需要注意的布尔值(imo) 您

例如,我有
var菜单\u ready=false。我有一个ajax函数,当ajax工作完成时,它会将
菜单\u ready
设置为true:

//set up event listener here

$(...).load(..., function() {
    ...
    menu_ready = true;
}
如何设置事件侦听器以等待
菜单\u ready
为真?

没有跨浏览器(跨平台)事件可以完成该任务。例如,对于对象属性有一些非常特定的机制,但是没有什么需要注意的布尔值(imo)

您希望在将该变量设置为true时也执行回调函数。您还可以应用一些jQuery sugar:

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

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

警告我下面的回答来自五月花号启航前一段时间。这是一个糟糕的答案。我无法删除它,因为它已被接受,并且系统不允许我删除已接受的答案。我可以编辑它使它更好,但为什么要这样做,当其他人给出了坚实的答案如下?底线:滚动浏览此页面以获得更充实的生活。:)

而且

<body onload="checkMenu();">


为什么不创建一个函数menuReady,它将在需要时启动

menuReady();

您不能将事件监听器附加到JavaScript变量本身,但可以伪造它。使用具有
get
set
listen
方法的对象,而不是布尔变量:

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;
}
您可以这样使用它:

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.

因为这是一个非常老的问题,而且很多答案都过时了,所以我想我应该添加一个更新的答案

背景

Javascript是一种事件驱动语言。因此,除了第一次加载页面时,环境中任何时候发生的任何更改都是由某种事件引起的。因此,传达更改的最佳方式是使用事件。您可以收听导致您想要观看的更改的同一事件,也可以创建一个新事件,让人们知道某些特定的更改

js有一个非常有用的eventEmitter对象,它是纯Javascript(不涉及DOM)。如果需要独立于DOM的通用事件机制,也可以在浏览器中使用相同的代码

浏览器DOM有自己的事件通知系统,您可以在其中创建事件、触发事件和侦听事件

轮询更改(正如这里公认的答案所示)通常是一种“黑客”行为,效率低下,可能会错过更改,不一定及时,会浪费电池和CPU等。。。如果你控制代码,总有比轮询更好的方法来设计它

OP的实际问题

仍然没有有效的机制来监控变量更改,但OP的问题实际上是有人想知道何时触发此代码:

$(...).load(..., function() {
    ...
    menu_ready = true;
}
当然,一个简单的答案是,任何想知道何时准备就绪的人也可以使用
$(…).load()
监视相同的内容,但这会将他们的通知与具体实现方式联系起来

创建我们自己的事件通知,任何人都可以收听

相反,更好的方法是创建我们自己的事件,当我们知道菜单已经准备好时,我们触发该事件。然后,代码中任何地方的任何人都可以监听同一事件

浏览器已经内置了一个可扩展的事件系统,如前所述。所以,我们可以在这里使用它。您需要选择一些众所周知的对象来触发任何侦听器想要注册以了解此情况时存在的事件。因为OP没有显示任何特定的上下文,所以我将只选择
窗口
对象

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

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

    // Dispatch the event.
    window.dispatchEvent(event);        
 }
注意,您可以使用任何DOM对象作为事件源(对您的应用程序最有意义的任何对象),只要它同时存在于有人想要注册事件的时间和事件发生的时间

然后,代码中任何位置的侦听器都可以侦听此事件:

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

下面是一个实际工作的实现,它在按下按钮时触发事件

let button=document.getElementById(“按我”);
addEventListener(“单击”,函数(){
//创建新事件
var事件=新事件(“菜单准备就绪”);
//发送事件。
窗口。dispatchEvent(事件);
});
函数日志(x){
var div=document.createElement(“div”);
div.innerHTML=x;
document.getElementById(“log”).appendChild(div);
}
//然后创建一个侦听器
addEventListener(“菜单准备就绪”,函数(){
日志(“获取菜单准备事件”);
});
#log{margin top:50px;}

按我

为什么不在ajax回调返回后立即添加“if(menu_ready){code您想在事件侦听器上调用的代码}”呢?同意Cystack,除非您知道ajax回调正在设置
menu_ready=true,您甚至不需要
if
-直接在ajax回调中调用代码。代码可能并不总是直接出现在ajax代码之后。我只是需要它在任何时候执行,不管代码的位置如何,menu_ready是真的。可能是重复的哇,我当时是个新手。不不不不。。。。不是个好主意。。。。如果您不能控制布尔值,只需附加一个DOM操纵事件监听器或其他监听器。@Joseph您能提供详细信息吗?@Jonathan,实际上我认为
setTimeout(“checkMenu();”,1000)应该是
setTimeout(checkMenu,1000)工作,但我明白你的意思。谢谢乔纳森,这是一个很好的解决方案。它对我有用这绝对是一个很好的方法来检测其他变量何时改变,同时保持异步。竖起两个大拇指。一个变量可以在1000毫秒内更改多次。在某些情况下,这可能是正常的,但如果需要真正的事件侦听,这将是错误的。唯一的问题是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.
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]);}
                    });
            }
$(...).load(..., function() {
    ...
    menu_ready = true;
}
$(...).load(..., function() {
    ...
    menu_ready = true;

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

    // Dispatch the event.
    window.dispatchEvent(event);        
 }
 window.addEventListener("menu_ready", function() {
     console.log("menu is now ready");
 });