2009-06-01 2 views
39

Я реализую обратный вызов для javascript-библиотеки 3rdParty, и мне нужно вернуть значение, но мне нужно получить значение с сервера. Мне нужно сделать что-то вроде этого:

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

getJson использует XMLHttpRequest, который (я считаю) имеет как синхронные и асинхронные модели поведения, я могу использовать поведение synchronouse?

+3

И почему вы не можете использовать обратный вызов для возврата/получения значения? Кроме того, старайтесь избегать синхронного поведения в максимально возможной степени, поскольку оно блокирует пользовательский интерфейс браузера во время его обработки. – PatrikAkerstrand

+0

Код вызова не поддерживает обратные вызовы. – tpower

ответ

103

Глядя на исходный код JQuery, все это делает $.getJSON:

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

И все это делает $.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 
    }); 
}, 

Нет черной магии там. Так как вам нужно настроить материал, отличных от основного $.getJSON функциональности, вы можете просто использовать функцию низкого уровня $.ajax и передать async option в ложном:

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

Отличный ответ :-) –

+0

, когда вы передаете 'async: false', тогда как вы получите сообщение об ошибке из' $ .ajax'? –

+1

Эти удобные методы почти как пресетов для функции $ .ajax. Они полезны только в том случае, если вы используете эти точные параметры ajax. – styfle

3

Но если я не ошибаюсь, этот код не будет работать:

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

return json; 
} 

Поскольку $ .ajax возвращает объект XHR, а не разобранный объект json.

Вы должны были бы сделать что-то подобное:

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 

На самом деле, вероятно, гораздо аккуратнее способ достижения той же

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

Вы также можете использовать следующие, прежде чем сделать звонок :

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

Я не знаю сферы действия «асинхронного» свойства, я подозреваю, что это глобальная конфигурация. Поэтому подумайте, хотите ли вы изменить это значение на true после синхронного вызова.

пример:

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

Это работает! –

0

Сфера недвижимости асинхронном является глобальным, ваш метод будет синхронизировать вызов.

2

Если кто-нибудь должен сделать это в рельсах, у меня есть довольно чистый способ, как это:

Setup контроллер так:

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 

установки вызова в 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; 
} 

Конечно, не делайте этого с синхронизацией, если вам не нужно. О, и пока я показываю javascript с URL-адресами, проверьте JSRoutes ...это делает их действительно чистыми.

Смежные вопросы