javascript, подождите, пока что-то станет правдой, затем выполните действие - PullRequest
6 голосов
/ 19 февраля 2010

Ну, название вроде говорит, что мне нужно. Потому что в асинхронных тайм-аутах Javascript мне нужно знать, когда что-то становится истинным Я не хочу занятой.

Придумали:

function do_when(predicate, action, timeout_step) {
    if (predicate()) {
        action();
    } else {
        setTimeout(do_when, timeout_step, predicate, action, timeout_step);
    }
}

Это хороший Javascript или я могу сделать лучше?

Ответы [ 3 ]

6 голосов
/ 19 февраля 2010

В зависимости от предиката, вы можете приспособить вашу проблему к реализации схемы наблюдателя . Некоторое время назад я написал сообщение в блоге о создании объектов JavaScript с наблюдаемыми свойствами . Это действительно зависит от того, что предикат равен , но это может дать вам большую часть пути с таким кодом:

var observable = createObservable({ propToWatch: false });
observable.observe('propToWatch', function (oldValue, newValue) { 
    alert('propToWatch has changed from ' + oldValue + ' to ' + newValue); 
});
observable.propToWatch(true); // alert pops

Конечно, это может быть излишним для вашего примера. Поскольку он никогда не указывается явно (например, я не очень хороший блоггер), вот полный код, необходимый для этой работы:

var createMediator = function () {
    var events = {};
    return {
        subscribe: function (eventName, callback) {
            events[eventName] = events[eventName] || [];
            events[eventName].push(callback);
        },
        publish: function (eventName) {
            var i, callbacks = events[eventName], args;
            if (callbacks) {
                args = Array.prototype.slice.call(arguments, 1);
                for (i = 0; i < callbacks.length; i++) {
                    callbacks[i].apply(null, args);
                }
            }
        }
    };
};

var createObservable = function (properties) {
    var notifier = createMediator(), createObservableProperty, observable;
    createObservableProperty = function (propName, value) {
        return function (newValue) {
            var oldValue;
            if (typeof newValue !== 'undefined' &&
                value !== newValue) {
                oldValue = value;
                value = newValue;
                notifier.publish(propName, oldValue, value);
            }
            return value;
        };
    };
    observable = {
        register: function (propName, value) {
            this[propName] = createObservableProperty(propName, value);
            this.observableProperties.push(propName);
        },
        observe: function (propName, observer) {
            notifier.subscribe(propName, observer);
        },
        observableProperties: []
    };
    for (propName in properties) {
        observable.register(propName, properties[propName]);
    }
    return observable;
};

Мои наблюдаемые объекты внутренне используют небольшую инфраструктуру обработки событий (функция createMediator), которую я однажды написал для проекта. ( До реализации пользовательских событий, поддерживаемых jQuery. Да!) Опять же, это может или не может быть излишним для вашей необходимости, но я подумал, что это забавный хак. Наслаждайтесь!

0 голосов
/ 19 февраля 2010

если ваш предикат станет истинным при изменении переменной, вот другое решение:

скажем, что мы хотим записать 'Большой брат наблюдает за тобой', когда значение объекта a станет 2.

function observable (value, condition, callback){
    this.value = value;
    this.condition = condition;
    this.callback = callback;
}

observable.prototype = {
    get value () {
        return this._value;
    },
    set value (value) {
        this._value = value;
        if (this.condition && this.callback && this.condition (value)) {
            this.callback (value);
        }
    }
};

condition = function (value) {
    console.log ('condition', value);
    return value === 2;
}

callback = function (value) {
    console.info ('Big Brother is watching you!');
}

var a = new observable (0, condition, callback);

console.log ('set value to 1');
a.value = 1;
console.log ('set value to 2');
a.value = 2;
console.log ('set value to 3');
a.value = 3;

Вы можете попробовать этот пример в Firefox

0 голосов
/ 19 февраля 2010

Он достаточно приличный, если его достаточно легко читать и он прекрасно работает, то, как правило, это хороший javascript.

С точки зрения производительности, обычно лучше вызывать функцию всякий раз, когда происходит то, что установлено в true.Поэтому в любой функции, которая выполняется, чтобы predicate() возвращала true, вы можете просто вызвать action() в конце.Но я уверен, что это то, что вы бы сделали, если бы могли, верно?

Вы также можете посмотреть на использование обратного вызова, где вы регистрируете функцию javascript для определенной переменной или аргумента функции, и когда функциязапустить его выполняет любую функцию, которая была установлена ​​для переменной обратного вызова.

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