如何让jQuery执行同步而非异步的Ajax请求?

时间:2008-09-25 13:26:54

标签: javascript jquery ajax asynchronous

我有一个JavaScript小部件,它提供标准的扩展点。其中之一是beforecreate功能。它应该返回false以防止创建项目。

我使用jQuery在这个函数中添加了一个Ajax调用:

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,而不是在回调中。有没有办法使用jQuery或任何其他浏览器中的API执行同步AJAX请求?

15 个答案:

答案 0 :(得分:1106)

jQuery documentation:您指定异步选项为 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
    });
}

答案 1 :(得分:248)

您可以通过调用

将jQuery的Ajax设置置于同步模式
jQuery.ajaxSetup({async:false});

然后使用jQuery.get( ... );

执行Ajax调用

然后再打开一次

jQuery.ajaxSetup({async:true});

我想这与@Adam建议的效果相同,但对于想要将jQuery.get()jQuery.post()重新配置为更精细的jQuery.ajax()的人来说,它可能会有所帮助语法。

答案 2 :(得分:133)

出色的解决方案!我注意到当我尝试实现它时,如果我在success子句中返回一个值,那么它返回为undefined。我必须将它存储在变量中并返回该变量。这是我提出的方法:

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;
}

答案 3 :(得分:83)

所有这些答案都忽略了使用async:false进行Ajax调用将导致浏览器挂起直到Ajax请求完成。使用流控制库可以解决此问题,而无需挂起浏览器。以下是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();
}

答案 4 :(得分:49)

function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


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

答案 5 :(得分:24)

请注意,如果您正在进行跨域Ajax调用(使用JSONP) - 无法同步执行,{{ jQuery将忽略1}}标志。

async

对于JSONP调用,您可以使用:

  1. Ajax-调用您自己的域 - 并执行跨域调用服务器端
  2. 将代码更改为异步工作
  3. 使用"功能音序器"像Frame.js这样的库(这个answer
  4. 阻止UI而不是阻止执行(此answer)(我最喜欢的方式)

答案 6 :(得分:23)

注意:由于此警告消息,您不应使用async: false

  

从Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)开始,由于对用户体验的负面影响,主线程上的同步请求已被弃用。

Chrome甚至在控制台中发出警告:

  

主线程上的同步XMLHttpRequest因其对最终用户体验的不利影响而被弃用。如需更多帮助,请查看https://xhr.spec.whatwg.org/

如果您正在做这样的事情,这可能会破坏您的页面,因为它可能会在任何一天停止工作。

如果你想这样做仍然感觉如果它是同步但仍然没有阻塞那么你应该使用async / await,也可能是一些基于承诺的ajax,比如新的Fetch API

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

修改 当页面被用户导航或关闭时,chrome正在Disallowing sync XHR in page dismissal上工作。这涉及beforeunload,unload,pagehide和visibilitychange。

如果这是您的使用案例,那么您可能需要查看navigator.sendBeacon而不是

页面也可以使用http标头或iframe的allow属性禁用sync req

答案 7 :(得分:11)

我使用了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' dataType ,并将 .responseText 更改为 responseJSON

我还使用返回对象的 statusText 属性检索状态。请注意,这是Ajax响应的状态,而不是JSON是否有效。

后端必须以正确(格式正确)的JSON返回响应,否则返回的对象将是未定义的。

回答原始问题时需要考虑两个方面。一个是告诉Ajax同步执行(通过设置 async:false ),另一个是通过调用函数的return语句返回响应,而不是回调函数。

我也尝试过POST,但它确实有效。

我将GET更改为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;
}

请注意,上述代码仅适用于异步 false 的情况。如果您要设置 async:true ,则返回的对象 jqxhr 在AJAX调用返回时无效,仅在异步调用结束后才会生效,但这是设置响应变量为时已晚。

答案 8 :(得分:11)

使用async: false,您将获得一个被阻止的浏览器。 对于非阻塞同步解决方案,您可以使用以下命令:

ES6 / ECMAScript2015

使用ES6,你可以使用发电机& co library

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等待:

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
    })(); 
}

答案 9 :(得分:6)

这是一个例子:

$.ajax({
  url: "test.html",
  async: false
}).done(function(data) {
   // Todo something..
}).fail(function(xhr)  {
   // Todo something..
});

答案 10 :(得分:3)

首先,我们应该了解何时使用$ .ajax以及何时使用$ .get / $。发布

当我们需要对ajax请求进行低级别控制时,例如请求标头设置,缓存设置,同步设置等,然后我们应该使用$ .ajax。

$。get / $ .post:当我们不需要对ajax请求进行低级别控制时。只需简单地将数据发送到服务器。这是

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

因此我们无法使用其他功能(同步,缓存等)与$ .get / $。post。

因此对于ajax请求的低级控制(同步,缓存等),我们应该选择$ .ajax

 $.ajax({
     type: 'GET',
      url: url,
      data: data,
      success: success,
      dataType: dataType,
      async:false
    });

答案 11 :(得分:1)

这是我使用jQuery对ASYNC请求的简单实现。我希望这对任何人都有帮助。

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();

答案 12 :(得分:1)

由于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;
};

答案 13 :(得分:0)

这是我的“ 线程”命名空间:

  var Thread = {
    睡眠:功能(毫秒){
        var start = Date.now();

        而(true){
            var clock =(Date.now()-开始);
            如果(时钟> = ms)中断;
        }

    }
};
 

这就是我所说的:

  var d1 = new Date();
console.log('start'+ d1.toLocaleTimeString());
Thread.sleep(10000);
var d2 = new Date();
console.log('end'+ d2.toLocaleTimeString());
 

如果查看控制台,我们将得到以下结果:

 从1:41:21 PM开始
结束1:41:31 PM
 

答案 14 :(得分:-1)

由于原始问题是关于jQuery.get的,因此在这里值得一提的是(如提到的here),一个可以在{{1 }},但最好避免,因为不推荐使用异步async: false(浏览器可能会给出警告):

$.get()