Как я могу заставить jQuery выполнять синхронный, а не асинхронный запрос Ajax?



у меня есть виджет JavaScript, который предоставляет стандартные точки расширения. Одним из них является

3007   13  

13 ответов:

С документация jQuery: указать асинхронные на ложные чтобы получить синхронный запрос 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
    });
}

вы можете поместить настройку Ajax jQuery в синхронный режим, вызвав

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 приведет к зависанию браузера до завершения запроса Ajax. Использование библиотеки управления потоком позволит решить эту проблему без зависания браузера. Вот пример с рамка.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();
}
function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


//example use
var msg=getURL("message.php");
alert(msg);

имейте в виду, что если вы делаете междоменный вызов Ajax (с помощью JSONP) - вы не могу сделать это синхронно,async флаг будет проигнорирован jQuery.

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

для JSONP-вызовов можно использовать:

  1. Ajax-вызовите свой собственный домен-и сделайте междоменный вызов на стороне сервера
  2. измените свой код для работы асинхронно
  3. используйте библиотеку "function sequencer", такую как Frame.js (это ответ)
  4. блокировать пользовательский интерфейс вместо блокировки выполнения (это ответ) (мой любимый способ)

Примечание: Вы не должны использовать async из-за этого:

начиная с Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), синхронные запросы на основной поток были устаревшими из-за негативных последствий для пользовательского опыта.

Chrome даже предупреждает об этом в консоли:

синхронный XMLHttpRequest в основном потоке является устаревшим из-за его пагубных последствий для работы конечного пользователя. Для дополнительная помощь, проверьте https://xhr.spec.whatwg.org/.

Это может сломать вашу страницу, если вы делаете что-то подобное, так как он может перестать работать в любой день.

Если вы хотите сделать это так, как будто это синхронно, но все еще не блокируется, тогда вы должны использовать async/await и, вероятно, также некоторый ajax, основанный на обещаниях, таких как new Fetch API

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

я использовал ответ, данный 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 выполнять синхронно (установив async: false) и другой возвращает ответ через оператор return вызывающей функции, а не в функцию обратного вызова.

Я также попробовал его с POST, и это сработало.

Я изменил GET to POST и добавил данных: 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;
}

обратите внимание, что приведенный выше код работает только в том случае, когда асинхронные и ложные. Если вы должны были установить async: true возвращенный объект jqxhr не будет действительным во время возврата вызова AJAX, только позже, когда асинхронный вызов закончился, но это слишком поздно, чтобы установить ответ переменной.

С async: false вы получаете себе заблокированный браузер. Для неблокирующего синхронного решения вы можете использовать следующее:

ES6 / ECMAScript2015

С ES6 вы можете использовать генератор и библиотека co:

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

С ES7 вы можете просто использовать asyc await:

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, таким как настройки заголовка запроса, настройки кэширования, синхронные настройки и т. д.тогда мы должны пойти за $.Аякс.

$.получить.$/post: Когда мы не требуем низкого уровня контроля над запросом ajax.Только просто получить/отправить данные на сервер. - Это стенография

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

и, следовательно, мы не можете использовать другие функции(синхронизация,кэш и т. д.) с.$ получить.$/должность.

следовательно, для управления низким уровнем (синхронизация, кэш и т. д.) по запросу ajax, мы должны пойти на $.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 синхронная работа устарела я придумал следующее решение, которое обертывает XMLHttpRequest. Это позволяет упорядочивать запросы AJAX, оставаясь при этом асинхронным по своей природе, что очень полезно для одноразовых токенов 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;
};

Comments

    Ничего не найдено.