2009-06-01 14 views
39

Wdrażam wywołanie zwrotne dla biblioteki javascript 3rdParty i muszę zwrócić wartość, ale muszę pobrać wartość z serwera. Muszę zrobić coś takiego:

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

getJSON używa XMLHttpRequest który (wierzę) ma zarówno synchronicznych i asynchronicznych zachowania, które można używać zachowanie synchronouse?

+3

I dlaczego nie można użyć wywołania zwrotnego do zwracania/otrzymywania wartości? Staraj się także unikać zachowań synchronicznych tak często, jak to możliwe, ponieważ blokują one interfejs przeglądarki podczas przetwarzania. – PatrikAkerstrand

+0

Kod wywołujący nie obsługuje oddzwonień. – tpower

Odpowiedz

103

Patrząc na kod źródłowy jQuery, to wszystko $.getJSON robi:

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

A to wszystko $.get robi:

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 czarna magia istnieje. Ponieważ trzeba dostosować rzeczy inne niż podstawowe funkcje $.getJSON, można po prostu użyć funkcji niskiego poziomu $.ajax i przekazać async option jako fałsz:

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

Świetna odpowiedź :-) –

+0

kiedy przekazujesz 'async: false', to jak otrzymasz komunikat o błędzie z' $ .ajax'? –

+1

Te metody wygody są prawie jak ustawienia wstępne dla funkcji $ .ajax. Są przydatne tylko wtedy, gdy korzystasz z tych dokładnych opcji ajax. – styfle

3

Ale chyba się nie mylę ten kod nie działa:

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

return json; 
} 

Jako, że $ .ajax zwraca obiekt XHR, a nie sparsowany obiekt Json.

Trzeba by zrobić coś więcej takich jak:

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 

W rzeczywistości nie ma chyba dużo neater sposobem osiągnięcia tego samego

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

Można również użyć następujących przed dokonaniem połączenia :

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

Nie znam zakresu właściwości "asynchronicznej", podejrzewam, że jest to globalna konfiguracja. Zastanów się więc, czy chcesz zmienić to z powrotem na true po połączeniu synchronicznym.

przykład:

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

To działa! –

0

Zakres właściwości async ma charakter globalny, metoda zsynchronizuje połączenie.

2

Jeśli ktokolwiek ma to zrobić w szynach, mam dość czysty sposób tak:

konfiguracji kontroler tak:

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 

konfiguracji połączenia w 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; 
} 

Oczywiście nie rób tej synchronizacji, chyba że musisz. Aha i póki ja pokazuję javascript z adresami URL w tym, sprawdź JSRoutes ...sprawia, że ​​są naprawdę czyste.

Powiązane problemy