2012-04-02 75 views
7

Tengo una función de javascript que necesita hacer un cálculo numérico. Algunos de los números utilizados en este cálculo se almacenan en una base de datos, y diferirán dependiendo de cómo un usuario rellena un formulario en línea. Una vez que el usuario llena el formulario, harán clic en el botón CALCULAR. En este momento, en la función JS, me gustaría usar ajax para obtener valores de una base de datos que corresponda a algún otro valor elegido por el usuario.actualizar la variable de javascript con ajax en tiempo real

Para un ejemplo simple: hay 3 tamaños de camisetas, con diferentes precios basados ​​en cada tamaño (almacenados en la base de datos). El usuario elige el tamaño y cuando hacen clic en CALCULAR, uso ajax para obtener el precio asociado con el tamaño que eligieron.

La pregunta es, quiero usar ajax para actualizar algunas variables que usaré más adelante en el script. La forma en que trato de hacerlo ahora no funciona, la variable en el script no se actualiza desde ajax, solo puedo acceder al valor de la base de datos dentro de la función success de la llamada ajax. Entiendo que esto se debe a que ajax es asincrónico por naturaleza, y tarda un tiempo, esperando que los datos vuelvan del servidor, mientras la función continúa ejecutándose

En el siguiente ejemplo, la llamada ajax devuelve datos JSON , y tengo una función llamada isjson() que prueba si la cadena devuelta es de hecho datos JSON.

código Ejemplo:

function calculate_cost(){ 

    var price = 0; 
    var size = $('form#tshirt_form [name="size"] option:selected').val(); 
    $.ajax({ 
     url:'my_script.php', 
     type:'post', 
     data:'select=price&table=tshirts.prices&where=size = "' + size + '"', 
     success:function(data){ 
      if(isjson(data)){ 
       data = $.parseJSON(data); 
       data = data[0]; 
       price = data['price']; 
      }else{ 
       //display error getting data 
      } 
     } 
    }); 
    // continue code for calculation 
    // this alert will display "0", but I want the price from the database in there 
    alert(price); 
    //perhaps do other ajax calls for other bits of data 
    //... 
    return final_price; 
} 

¿Alguien sabe cómo puedo lograr esto, la actualización de las variables con el Ajax en tiempo real ??

¡Muchas gracias!

** ** EDITAR

Gracias a todos por la ayuda, entiendo sobre Ajax ser asíncrono. Realmente me gustaría una respuesta donde no tenga que continuar el cálculo dentro de la función success, porque mi problema real involucra muchos valores de bastantes tablas diferentes. También me gustaría poder ampliar el cálculo en el futuro sin que se vuelva demasiado intrincado. Si esto no es posible, tendré que vivir con eso. ;-)

** ** EDIT 2

OK, tenemos la respuesta: por supuesto que está justo en la parte superior de la página docs,: -/lo siento por eso. La propiedad async en la llamada jQuery ajax. http://api.jquery.com/jQuery.ajax/

+5

'de datos: 'query = precio de selección de tshirts.prices donde el tamaño = "' + tamaño + '"',' por favor, no hagas eso. ¿Qué pasa si 'data: 'query = drop table users'' – karim79

+2

Espero que hagas algo de saneamiento mega-inteligente de la entrada' data: query = 'parte – bububaba

+0

wow gracias, sí, podría ser catastrófico –

Respuesta

11

Eso se debe a que ajax ejecuta la solicitud asíncrona de forma predeterminada y antes de los alcances de control alert(price); la solicitud aún no se ha ejecutado y price todavía mantiene el valor anterior.

Si desea ejecutarlo sincrónicamente, puede establecer async en falso.

$.ajax({ 
    async: false, 
    ..... 
    ..... 
}); 
+0

¡¡Eso es todo !!! Por supuesto, lo más probable es que en los documentos: -/ –

2

es necesario calcular dentro de la función éxito

function calculate_cost(){ 

var price = 0; 
var size = $('form#tshirt_form [name="size"] option:selected').val(); 
$.ajax({ 
    url:'my_script.php', 
    type:'post', 
    data:'query=select price from tshirts.prices where size = "' + size + '"', 
    success:function(data){ 
     if(isjson(data)){ 
      data = $.parseJSON(data); 
      data = data[0]; 
      price = data['price']; 
      // continue code for calculation 
      // this alert will display "0", but I want the price from the database in there 
      alert(price); 
      //perhaps do other ajax calls for other bits of data 
      //... 
     }else{ 
      //display error getting data 
     } 
    } 
}); 

// return final_price; this function wont be able to return a value 
} 
1

ajax es asíncrona y por esta razón por la que debe refactorizar el código para que haga lo que tiene que hacer en la devolución de llamada

$.ajax({ 
    url:'my_script.php', 
    type:'post', 
    data:'query=select price from tshirts.prices where size = "' + size + '"', 
    success:function(data){ 
     if(isjson(data)){ 
      data = $.parseJSON(data); 
      data = data[0]; 
      price = data['price']; 
      //call another function (maybe make another ajax call) from here 
      dosomethingwithprice(price); 
     }else{ 
      //display error getting data 
     } 
    } 
}); 
1

Su código Ajax saca tiempo para ejecutar (aunque no mucho) ; sin embargo, el código después de la llamada AJAX se ejecuta de forma asíncrona, y muy probablemente antes de que los resultados de la llamada ajax entrar.

lugar, ¿por qué no intenta mover alerta (precio) en el cuerpo de la región if(isjson(data)), y luego, ejecuta una función de devolución de llamada que devuelve el precio a cualquier otra utilidad para la que lo necesites.

1

tiene que hacer su cálculo dentro de la pila de devolución de llamada. Ajax funciona de manera asíncrona, eso significa que, la función de devolución de llamada de códigos externos se ejecuta antes de que comience la función de devolución de llamada. Entonces deberías hacer tu cálculo en devolución de llamada.

function calculate_cost(){ 

    var price = 0; 
    var size = $('form#tshirt_form [name="size"] option:selected').val(); 
    $.ajax({ 
     url:'my_script.php', 
     type:'post', 
     data:'query=select price from tshirts.prices where size = "' + size + '"', 
     success:function(data){ 
      if(isjson(data)){ 
       data = $.parseJSON(data); 
       data = data[0]; 
       price = data['price']; 
      }else{ 
       //display error getting data 
      } 

    // continue code for calculation 
    // this alert will display "0", but I want the price from the database in there 
    alert(price); 
    //perhaps do other ajax calls for other bits of data 
    //... 
     return final_price; 
     } 
    }); 

} 
+0

Sí, sé que ajax funciona de forma asíncrona, es por eso que lo agregué en mi pregunta. Quería hacer una forma de hacerlo donde no tenga que seguir poniendo mi otro código dentro de la función 'success'. –

+0

'return final_price;' no devolverá un valor de la función primaria, que simplemente sale de la devolución de llamada ajax. @jeffery_the_wind: la estructura de este método debe modificarse para que calculate_cost() devuelva un objeto diferido en lugar de un valor. –

0

Sugiero que la llamada ajax devuelva un objeto diferido. Luego, cuando el precio final está completamente calculado, resuelva el objeto diferido con ese valor.

function calculate_cost() { 
    var price = 0, 
     size = $('#tshirt_form [name="size"] option:selected').val(), 
     def = $.Deferred(); 

    $.ajax({ 
     data: {size:size}, 
     url: 'my_script.php', 
     type: 'post', 
     dataType: 'json', 
    }).done(function(data){ 
     data = data[0]; 
     price = data['price']; 
     def.resolve(price); 
    }).fail(function(){ 
     // do on error stuff 
    }); 

    return def.promise(); 
} 
// ... 
calculate_cost("large").done(function(price){ 
    alert(price); 
}).fail(function(){ 
    alert("Failed to retrieve price"); 
}); 
Cuestiones relacionadas