2010-02-19 14 views
5

Beh, il titolo dice di cosa ho bisogno. Perché nei timeout JavaScript asincroni ho bisogno di sapere quando qualcosa diventa vero. Non voglio busyloop.javascript, aspetta che qualcosa sia vero, quindi esegui l'azione

si avvicinò con:

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

È bene Javascript o posso fare meglio?

+0

Qual è il predicato? – SLaks

+0

@predicate è la funzione, l'azione è anche la funzione – zaharpopov

+0

Il predicato è la condizione in cui deve essere true prima che l'azione venga chiamata. ** ==> ** Sembra sano per me. – AxelEckenberger

risposta

0

È abbastanza decente, se è abbastanza facile da leggere e funziona bene, quindi è generalmente buono javascript.

Per quanto riguarda le prestazioni, in genere è meglio chiamare la funzione ogni volta che ciò che è impostato su true accade. Pertanto, in qualsiasi funzione eseguita per rendere predicate() restituito true, è possibile chiamare semplicemente action() alla fine. Ma sono sicuro che è quello che avresti fatto se potessi, giusto?

Si può anche utilizzare un callback, in cui si registra una funzione javascript su una particolare variabile o argomento di funzione e quando viene eseguita la funzione, esegue qualsiasi funzione impostata sulla variabile di callback.

-1

se il predicato diventare vero quando un cambio variabile, qui è un'altra soluzione:

dicono che vogliamo log 'Grande fratello ti guarda' quando il valore dell'oggetto a diventare 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; 

puoi provare questo esempio in firefox

+1

cosa si ottiene e si imposta? è questo javascript standard? – zaharpopov

+1

Getter e setter non funzioneranno in tutte le implementazioni javascript. –

+0

questo non funzionerà meno hai firebug installato e aperto. (perché stai usando la console) – Samuel

6

A seconda del predicato, potresti essere in grado di adattare il problema a un'implementazione di observer pattern. Qualche tempo fa ho scritto un post sul blog su creating JavaScript objects with observable properties. Dipende da cosa predicato è, ma questo potrebbe ottenere la maggior parte del tragitto con il codice come questo:

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

Naturalmente, questo potrebbe essere eccessivo per il tuo esempio. Dal momento che non è mai elencato esplicitamente (nb io non sono un buon blogger), ecco il codice completo necessario per fare questo lavoro:

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; 
}; 

miei oggetti osservabili fanno uso interno di un piccolo quadro eventing (la funzione createMediator) Ho scritto una volta per un progetto. (Prima di realizzando eventi personalizzati supportati da jQuery. D'oh!) Ancora una volta, questo potrebbe o non potrebbe essere eccessivo per le tue necessità, ma ho pensato che fosse un trucco divertente. Godere!

+0

Ora che guardo di nuovo questo codice, vorrei poter scrivere 'observable.propToWatch.observe (function() {...})'. Oh bene. Forse potrei armeggiare ancora un po 'in futuro. –

Problemi correlati