2009-06-01 10 views
39

Sto implementando un callback per una libreria javascript 3rdParty e ho bisogno di restituire il valore, ma ho bisogno di ottenere il valore dal server. Ho bisogno di fare qualcosa di simile:

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

getJSON utilizza XMLHttpRequest, che (credo) ha entrambi i comportamenti sincrone e asincrone, posso utilizzare il comportamento synchronouse?

+3

E perché non è possibile utilizzare una richiamata per restituire/ottenere il valore? Inoltre, cerca di evitare il più possibile il comportamento sincrono, poiché bloccherà l'interfaccia utente del browser durante l'elaborazione. – PatrikAkerstrand

+0

Il codice chiamante non supporta la richiamata. – tpower

risposta

103

Guardando il codice sorgente di jQuery, questo è tutto $.getJSON fa:

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

E questo è tutto $.get fa:

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 magia nera lì. Dal momento che è necessario personalizzare roba diversa dalla funzionalità di base $.getJSON, si può semplicemente utilizzare la funzione di basso livello $.ajax e passare il async option come falso:

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

Ottima risposta :-) –

+0

quando si passa 'async: false', come si ottiene il messaggio di errore da $ .ajax'? –

+1

Questi metodi di convenienza sono quasi come predefiniti per la funzione $ .ajax. Sono utili solo se stai usando quelle opzioni ajax esatte. – styfle

3

Ma se non erro questo codice non funzionerebbe:

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

return json; 
} 

Come $ .ajax restituisce l'oggetto XHR non l'oggetto json analizzato.

Lei avrebbe bisogno di fare qualcosa di più simile:

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 

In realtà non v'è probabilmente un modo molto più ordinato di raggiungere lo stesso

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

È inoltre possibile utilizzare il seguente prima di effettuare la chiamata :

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

non so il campo di applicazione della proprietà "asincrona", ho il sospetto che si tratta di un configurazione globale Quindi considera se vuoi riportarlo a true dopo la tua chiamata sincrona.

esempio:

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

Questo funziona! –

0

Il campo di applicazione della proprietà asincrona è globale, il metodo sarà sincronizzare la chiamata.

2

Se qualcuno ha mai fare questo in rotaie, ho un modo abbastanza pulito come questo:

Imposta il controller in questo modo:

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 

Imposta la chiamata in 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; 
} 

Ovviamente, non eseguire questa sincronizzazione a meno che non sia necessario. Oh e mentre sto mostrando javascript con gli URL in esso, controlla JSRoutes ...li rende davvero puliti.

Problemi correlati