Как вы делаете прослушиватель событий, который обнаруживает, что булева переменная становится истинной? - PullRequest
6 голосов
/ 22 июля 2011

Например, у меня есть var menu_ready = false;. У меня есть функция AJAX, которая устанавливает menu_ready в значение true, когда выполняется AJAX:

//set up event listener here

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

Как мне настроить прослушиватель событий, который ожидает menu_ready, чтобы быть истиной?

Ответы [ 7 ]

7 голосов
/ 22 июля 2011

Вы не можете присоединить слушателей событий к переменным 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.
2 голосов
/ 22 июля 2011

Вы не можете прикрепить прослушиватели событий к отдельным переменным.

Лучший способ сделать это - поместить переменную в объект и сделать так, чтобы все пользователи этой переменной обращались к ней через методы «get» и «set»или более конкретно названные методы.При установке значения вы можете проверить, действительно ли значение изменяется так, как вас интересует, и действовать соответствующим образом.Вот пример:

var _isMenuReady = false;    // do not access this directly
function isMenuReady() {
    return(_isMenuReady);
}
function setMenuReady(val) {
    if (arguments.length < 1) {
        val = true;
    }
    if (!_isMenuReady && (val)) {
        _isMenuReady = val;
        // _isMenuReady has gone from false to true
        // do whatever you need to do now
    }
    _isMenuReady = val;
}

// sample code
var ready = isMenuReady();    // returns whether the menu is ready or not
setMenuReady();               // sets the menu to be ready now
setMenuReady(false);          // sets it back to not ready

Можно даже сделать его закрытым членом объекта, чтобы никто не мог получить к нему доступ непосредственно за пределами реальных методов доступа (хотя это не требуется, если весь код принадлежит вам ивы сотрудничаете, не обращаясь к переменной напрямую).Но, если вы хотите сделать его по-настоящему приватным, см. эту статью для получения информации о том, как сделать частных пользователей.По сути, вы создаете длительное закрытие функции, локальные переменные которого доступны только внутри функции.Это классная техника.

function menuReadyTracker(initialValue) {

    var value = initialValue;
    var subscribers = [];

    this.get = function () {
        return(value);
    };

    this.set = function(newVal) {
        if (newVal != value) {
            value = newVal;
            var o;
            for (var i = 0; i < subscribers.length; i++) {
                o = subscribers[i];
                o.func.call(o.ctx, o.data);
            }
        }
    }

    // call subscribe to register a notification callback
    this.subscribe = function(f, data, ctx) {
        var o = {};
        o.func = f;
        o.data = data;
        o.ctx = ctx || window;
        subscribers.push(o);
    }

    // call unsubscribe to remove a notification callback
    this.unsubscribe = function(f, data, ctx) {
        var o;
        var newSubscribers = [];
        for (var i = 0; i < subscribers.length; i++) {
            o = subscribers[i];
            if (o.func != f || o.data != data || o.ctx != ctx) {
                newSubscribers.push(o);   // copy if it doesn't match
            }
        }
        subscribers = newSubscribers;
    }
}

var menuReady = new menuReadyTracker(false);
menuReady.subscribe(myNotification, "in real-time.");

console.log(menuReady.get());

menuReady.set(true);
console.log(menuReady.get());

// this function gets called whenever the menu flag goes from false to true
// you can have as many subscribers to this notification as you want and 
// they code that handles the notifications can be anywhere you want in your
// code base as the notification handlers are registered with the subscribe method
function myNotification(data) {
    alert("I got notified " + data);
}

jsFiddle: http://jsfiddle.net/jfriend00/PYJef/

2 голосов
/ 22 июля 2011

Не существует кросс-браузерного (кроссплатформенного) события, которое выполнит эту работу.Есть несколько довольно специфических механизмов для просмотра, например, свойств объектов, но нечего ожидать булевых (imo).

Вы хотите также выполнить функцию обратного вызова, когда выустановив эту переменную в true.Вы также можете применить немного сахара jQuery:

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

$('#foobar').load('/some/code', function() {
    menu_ready = true;
}).done( myCallbackReference );
1 голос
/ 22 июля 2011
function menuReady(){
  // Do whatever it is you need done when menu is ready
}    

$(...).load(..., function() {
  menuReady();// menuReady is called on callback    
});
1 голос
/ 22 июля 2011

Один из способов - непрерывный опрос:

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

и ...

<body onload="checkMenu();">
0 голосов
/ 11 февраля 2015
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]);}
                    });
            }
0 голосов
/ 22 июля 2011

Почему бы не создать функцию menuReady, которая будет срабатывать при желании?

menuReady();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...