У меня есть виджет JavaScript, который предоставляет стандартные точки расширения. Одним из них является функция beforecreate
. Она должна возвращать false
, чтобы предотвратить создание элемента.
Я добавил Ajax вызов в эту функцию, используя jQuery:
beforecreate: function (node, targetNode, type, to) {
jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
function (result) {
if (result.isOk == false)
alert(result.message);
});
}
Но я хочу, чтобы мой виджет не создавал элемент, поэтому я должен вернуть false
в материнской функции, а не в обратном вызове. Есть ли способ выполнить синхронный AJAX-запрос с помощью jQuery или любого другого внутрибраузерного API?
Из документации jQuery: вы указываете параметр asynchronous равным false, чтобы получить синхронный Ajax-запрос. Тогда ваш обратный вызов может установить некоторые данные до того, как ваша материнская функция выполнится.
Вот как будет выглядеть ваш код, если его изменить, как было предложено:
beforecreate: function (node, targetNode, type, to) {
jQuery.ajax({
url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
success: function (result) {
if (result.isOk == false) alert(result.message);
},
async: false
});
}
Вы можете перевести настройку jQuery's Ajax в синхронный режим, вызвав вызов
jQuery.ajaxSetup({async:false});
А затем выполнять вызовы Ajax, используя jQuery.get( ... );
.
Затем просто включите его снова один раз
jQuery.ajaxSetup({async:true});
Я думаю, что это работает так же, как предложил @Adam, но это может быть полезно для тех, кто хочет перенастроить свои jQuery.get()
или jQuery.post()
на более сложный синтаксис jQuery.ajax()
.
Отличное решение! Когда я пытался его реализовать, я заметил, что если я возвращаю значение в пункте success, оно возвращается как неопределенное. Мне пришлось хранить его в переменной и возвращать эту переменную. Вот какой метод я придумал:
function getWhatever() {
// strUrl is whatever URL you need to call
var strUrl = "", strReturn = "";
jQuery.ajax({
url: strUrl,
success: function(html) {
strReturn = html;
},
async:false
});
return strReturn;
}
Все эти ответы упускают тот момент, что делает AJAX-вызов с async:false приведет к браузеру, чтобы повесить, пока запрос завершится Аякс. С помощью управления потоком библиотеки позволит решить эту проблему, не вешая браузер. Вот пример с Frame.js:
beforecreate: function(node,targetNode,type,to) {
Frame(function(next)){
jQuery.get('http://example.com/catalog/create/', next);
});
Frame(function(next, response)){
alert(response);
next();
});
Frame.init();
}
Имейте в виду, что если вы'повторно делать кросс-доменные AJAX-вызов (с помощью JSONP в) - Вы можете'т делать это синхронно, "асинхронный" флаг будет проигнорирован на jQuery.
$.ajax({
url: "testserver.php",
dataType: 'jsonp', // jsonp
async: false //IGNORED!!
});
Для JSONP-вызовов можно использовать:
Примечание: Вы должны'т использовать асинхронные: ложные из-за этого предупреждения:
&ГТ; начиная с Gecko 30.0 (для Firefox 30.0 / 30.0 Тандерберд / не Opera 2.27), синхронных запросов в основном потоке были осуждены из-за негативного воздействия на работу пользователя.
Хром даже предупреждает об этом в консоли:
&ГТ; синхронные запросы XMLHttpRequest в основной нити является устаревшим из-за его негативного воздействия на конечного пользователя's опыт. Для получения дополнительной помощи, проверить https://xhr.spec.whatwg.org/.
Это может сломать вашу страницу, если вы делаете что-то вроде этого, поскольку она может перестать работать в любой день.
Если вы хотите сделать это таким образом, что по-прежнему чувствует себя, как если бы это's синхронный, но до сих пор не'т блок, то вы должны использовать async/await и наверное тоже какой-нибудь "Аякс", который основан на обещания, как новый принести API-интерфейс
async function foo() {
var res = await fetch(url)
console.log(res.ok)
var json = await res.json()
console.log(json)
}
Редактировать хром работает на запрет синхронизации XHR в увольнение страницы когда страница выполняется переход или закрыты пользователем. Это предполагает beforeunload, разгрузить, pagehide и visibilitychange.
если это ваш случай, то, возможно, захотите, чтобы взглянуть на навигатор.sendBeacon](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon) вместо
Это также возможно для этой страницы, чтобы отключить синхронизацию требуется с помощью HTTP-заголовков или iframe's позволяют атрибут
Я использовал ответ Carcione и изменил его, чтобы использовать JSON.
function getUrlJsonSync(url){
var jqxhr = $.ajax({
type: "GET",
url: url,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
function testGetUrlJsonSync()
{
var reply = getUrlJsonSync("myurl");
if (reply.valid == 'OK')
{
console.dir(reply.data);
}
else
{
alert('not valid');
}
}
Я добавил тип в 'в формате JSON' и изменен .responseText в responseJSON.
Я также проверено состояние с помощью statustext также свойства возвращаемого объекта. Обратите внимание, что это состояние AJAX ответ, Не будь JSON является допустимым.
Админцентр должен вернуть ответ в правильный (хорошо сформированной) в формате JSON, в противном случае возвращенный объект будет неопределена.
Есть два аспекта следует учитывать при ответе на исходный вопрос. Один говорит AJAX, чтобы выполнять синхронно (посредством установки асинхронные: ложные), а другая возвращает ответ через вызов функции'возвращение заявления, а не в функцию обратного вызова.
Я также попробовал его с должности, и он работал.
Я поменяла вам на пост и добавил данные: postdata
function postUrlJsonSync(url, postdata){
var jqxhr = $.ajax({
type: "POST",
url: url,
data: postdata,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
Обратите внимание, что приведенный выше код работает только в том случае, когда асинхронность является ложь. Если вы были задавать асинхронные: правда возвращенный объект jqxhr не действует во время AJAX-вызов возвращает, только позже, когда асинхронный вызов завершен, но это слишком поздно, чтобы установить ответ переменной.
С использованием ключевых слов async: false`, вы получите заблокированный браузер. Для неблокирующей синхронного решения можно использовать следующие:
С ЕС6 вы можете использовать генератор &ампер; сотрудничество библиотек:
beforecreate: function (node, targetNode, type, to) {
co(function*(){
let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
});
}
С ES7 вы можете просто использовать асинхронная ждут:
beforecreate: function (node, targetNode, type, to) {
(async function(){
let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
})();
}
Это пример:
$.ajax({
url: "test.html",
async: false
}).done(function(data) {
// Todo something..
}).fail(function(xhr) {
// Todo something..
});
Во-первых, мы должны понять, когда мы используем $.AJAX и когда мы используем $.получите/$.пост
Когда мы требуем низкий уровень контроля за AJAX-запроса, такие как параметры заголовка запроса, настройки кэширования, синхронные параметры и т. д. затем мы должны пойти на $.Аякс.
$.получите/$.сообщение: Когда мы не требуем низкий уровень контроля за AJAX-запрос.Только просто получить/отправить данные на сервер.Это стенография
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
и поэтому мы не можем использовать другие функции(синхронизация,кэш и т. д.) с $.получите/$.пост.
Следовательно, низкий уровень управления(синхронизации,кэш и т. д.) за AJAX-запрос,мы должны идти за $.Аякс
$.ajax({
type: 'GET',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
это моя простая реализация для асинхронных запросов с помощью jQuery. Я надеюсь, что это поможет кому-либо.
var queueUrlsForRemove = [
'http://dev-myurl.com/image/1',
'http://dev-myurl.com/image/2',
'http://dev-myurl.com/image/3',
];
var queueImagesDelete = function(){
deleteImage( queueUrlsForRemove.splice(0,1), function(){
if (queueUrlsForRemove.length > 0) {
queueImagesDelete();
}
});
}
var deleteImage = function(url, callback) {
$.ajax({
url: url,
method: 'DELETE'
}).done(function(response){
typeof(callback) == 'function' ? callback(response) : null;
});
}
queueImagesDelete();
Потому что XMLHttpReponseсинхронной работы является устаревшим, я придумал следующее решение, которое обертывает
запрос`. Это позволяет заказать Аякс запросы, в то же время asycnronous в природе, что очень полезно для одноразового использования CSRF токены.
Он тоже прозрачными, так и библиотек, таких как jQuery будет работать без проблем.
/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
var xhr = new _XMLHttpRequest();
var _send = xhr.send;
xhr.send = function()
{
/* queue the request, and if it's the first, process it */
XHRQueue.push([this, arguments]);
if (XHRQueue.length == 1)
this.processQueue();
};
xhr.processQueue = function()
{
var call = XHRQueue[0];
var xhr = call[0];
var args = call[1];
/* you could also set a CSRF token header here */
/* send the request */
_send.apply(xhr, args);
};
xhr.addEventListener('load', function(e)
{
/* you could also retrieve a CSRF token header here */
/* remove the completed request and if there is more, trigger the next */
XHRQueue.shift();
if (XHRQueue.length)
this.processQueue();
});
return xhr;
};
Это мой “поток” пространство имен:
var Thread = {
sleep: function(ms) {
var start = Date.now();
while (true) {
var clock = (Date.now() - start);
if (clock >= ms) break;
}
}
};
И это, как я называю это:
var d1 = new Date();
console.log('start ' + d1.toLocaleTimeString());
Thread.sleep(10000);
var d2 = new Date();
console.log('end ' + d2.toLocaleTimeString());
И если смотреть на консоль мы получим следующий результат:
start 1:41:21 PM
end 1:41:31 PM