Quiero volver a ejecutar periódicamente algún método que dependa de los datos recuperados del servidor *. Sin embargo, también quiero almacenar en caché esos datos y solo llegar al servidor una vez.

Si fuera jQuery, haría algo como

function draw() {
  var data = undefined;

  // Pre-data retrieval code
  var foo, bar, alpha, beta, gamma, etc.
  ...

  if (data == undefined) {
    $.ajax({
      ...
      async: false, // IMPORTANT PART
      success: function(data) {
         data = processData(data);
      }
    });
  }

  doSomethingComplex(data);

  // Defined within to inherit scope
  // i.e., don't want to pass in foo, bar, alpha, beta, gamma, etc.
  function doSomethingComplex() {...}
}

Sin embargo, las funciones XHR de d3 parecen codificar el parámetro async en verdadero. Entonces me encuentro haciendo algo como

if (data != undefined) doSomething(data);
else {
  d3.json(..., function(data) {
    data = processData(data);
    doSomething(data);
    }
}

1) ¿Qué otros diseños hay para almacenar en caché y decidir si realizar una llamada AJAX? Específicamente en d3.

2) La definición de doSomethingComplex dentro de la función draw (para evitar pasar muchos parámetros) parece vago. ¿Alguna ventaja de pasar cada variable?

* Mi caso específico es volver a dibujar un gráfico de barras d3 en el cambio de tamaño de la ventana (no me gustó cómo viewBox y preserveAspectRatio manejaron el cambio de tamaño del texto). Con mucho gusto escucharé otras sugerencias para volver a dibujar en el cambio de tamaño, pero estoy interesado en sugerencias para el diseño anterior

0
lebolo 2 sep. 2014 a las 18:10

2 respuestas

La mejor respuesta

Su segundo ejemplo es la mejor manera. Hacer una llamada Ajax con sync: true lo hace síncrono y anula el propósito de hacer una llamada AJAX (recuerda lo que significa la llamada A en AJAX).

En cuanto a llamar a doSomethingComplex dentro del sorteo es bueno o malo, es algo difícil de responder sin mirar a un nivel holístico en todo su diseño. En la superficie, viola SRP, pero luego, con JavaScript, a veces hacerlo puede hacer que todo flujo de código lógico y más fácil de seguir. Tiendo a cambiar el dogmatismo a favor del pragmatismo cuando tiene sentido.

Diría que intente refactorizar el código para que no sea necesario llamar a doSomethingComplex en el sorteo y ver si eso tiene más sentido. En general, cuantas menos tareas realice una sola función, más fácil será probar y mantener el código, sin olvidar la menor posibilidad de que tenga errores.

Para reducir la cantidad de variables requeridas para pasar, siempre puede envolverlas en un solo objeto:

var state = {
 foo: ...,
 bar: ...
 ...
};

doSomethingComplex(state);

Al pasar un estado como este, también evitará los efectos secundarios relacionados con el cierre. No digo que los cierres siempre sean malos, pero si puedes tener una cosa menos de qué preocuparte, ¿por qué no hacer eso?

Una vez más, todo esto depende de cómo encajan las cosas en la imagen más grande y usa estos puntos como una luz de guía. No hay bala de plata.

2
Mrchief 2 sep. 2014 a las 16:11

No creo que deba sentirse incómodo con el uso de cierres. Por cierto, me gusta su segundo ejemplo de código más que el primero con el código de "sincronización". Puede parecer más directo a alguien que no está acostumbrado a los cierres, pero esto es solo una cuestión de acostumbrarse.

¿Hay algo al lado del "gusto" que te haga sentir incómodo con el segundo ejemplo?

2
levus.lazarus 2 sep. 2014 a las 14:26