2009-06-01 6 views
39

Estoy implementando una devolución de llamada para una biblioteca de JavaScript de 3rdParty y necesito devolver el valor, pero necesito obtener el valor del servidor. Necesito hacer algo como esto:

3rdPartyObject.getCustomValue = function { 
    return $.getJSON('myUrl'); 
} 

getJSON utiliza XMLHttpRequest, que (creo) ha ambos comportamientos sincrónicos y asincrónicos, puedo utilizar el comportamiento synchronouse?

+3

¿Y por qué no puede usar una devolución de llamada para regresar/obtener el valor? Además, intente evitar el comportamiento síncrono tanto como sea posible, ya que bloqueará la interfaz de usuario del navegador durante su procesamiento. – PatrikAkerstrand

+0

El código de llamada no admite devolución de llamada. – tpower

Respuesta

103

Mirando el código fuente jQuery, esto es todo lo hace $.getJSON:

getJSON: function(url, data, callback) { 
    return jQuery.get(url, data, callback, "json"); 
}, 

Y esto es todo lo hace $.get:

get: function(url, data, callback, type) { 
    // shift arguments if data argument was omitted 
    if (jQuery.isFunction(data)) { 
     callback = data; 
     data = null; 
    } 

    return jQuery.ajax({ 
     type: "GET", 
     url: url, 
     data: data, 
     success: callback, 
     dataType: type 
    }); 
}, 

No hay magia negro allí. Ya que se necesita para personalizar cosas aparte de la funcionalidad básica $.getJSON, sólo puede utilizar la función de bajo nivel $.ajax y pasar el async option como falso:

$.ajax({ 
    type: 'GET', 
    url: 'whatever', 
    dataType: 'json', 
    success: function() { }, 
    data: {}, 
    async: false 
}); 
+8

Gran respuesta :-) –

+0

cuando pasa 'async: false', ¿cómo se obtiene el mensaje de error de' $ .ajax'? –

+1

Esos métodos de conveniencia son casi como presets para la función $ .ajax. Solo son útiles si estás usando esas opciones exactas de Ajax. – styfle

3

Pero si no me equivoco este código no funcionaría:

3rdPartyObject.getCustomValue = function { 
    var json = $.ajax({ 
    type: 'GET', 
    url: 'whatever', 
    dataType: 'json', 
    success: function() { }, 
    data: {}, 
    async: false 
    }); 

return json; 
} 

Como $ .ajax vuelve no el objeto XHR el objeto JSON analizada.

Usted tendría que hacer algo más como:

var jsonLoader = function(url){ 
    this.url = url; 
    this.rawData = {}; 
    this.getRawData(); 
}; 

jsonLoader.prototype.getRawData = function(){ 

    var json = $.ajax({ 
     type: 'GET', 
     url: this.url, 
     dataType: 'json', 
     success: this.getRawData(this), 
     data: {}, 
     async: false 
    }); 
}; 

jsonLoader.prototype. getRawData = function(self){ 
    return function(json){self.rawData = json;}; 
}; 

var loadMe = new jsonLoader("Data.json"); 
loadMe.rawData //has the parsed json object 

De hecho, no es probablemente una manera mucho más ordenado de conseguir el mismo

7
var jsonObjectInstance = $.parseJSON(
    $.ajax(
     { 
      url: "json_data_plz.cgi", 
      async: false, 
      dataType: 'json' 
     } 
    ).responseText 
); 
15

También puede utilizar el siguiente antes de hacer su llamada :

$.ajaxSetup({ "async": false }); 

No conozco el alcance de la propiedad "async", sospecho que es una configuración global Así que considere si desea cambiar esto a verdadero después de su llamada síncrona.

ejemplo:

3rdPartyObject.getCustomValue = function { 
    $.ajaxSetup({ "async": false }); 
    var result = $.getJSON('myUrl'); 
    $.ajaxSetup({ "async": true }); 
    return result; 
} 
+1

¡Esto funciona! –

0

El alcance de la propiedad asíncrono es global, su método se sincronizará la llamada.

2

Si alguien alguna vez tiene que ver esto en los carriles, tengo una manera bastante limpio como esto:

Configuración de su controlador de la siguiente manera:

def my_ajax_action 

    respond_to do |format| 
     # if you use render, you won't need a view page, the ":json =>" part takes care of all 
     # the formatting 
     format.json { render :json => @variable_containing_json } 
    end 

end 

instalación de la llamada en Javascript

function doAjaxWork() { 

    var ret; 

    $.ajax({ 
     type: 'GET', 
     url: '/controller/action/param', 
     dataType: 'json', 
     complete: function(response) { 
      ret = eval('(' + response.responseText + ')'); 
     }, 
     async: false 
    }); 


    return ret; 
} 

Por supuesto, no hacer estas cosas sincronización a menos que tenga que hacerlo. Ah, y mientras estoy mostrando javascript con urls, echa un vistazo a JSRoutes ...lo hace realmente limpio.

Cuestiones relacionadas