Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何让jQuery执行同步而不是异步的Ajax请求?_Javascript_Jquery_Ajax_Asynchronous - Fatal编程技术网

Javascript 如何让jQuery执行同步而不是异步的Ajax请求?

Javascript 如何让jQuery执行同步而不是异步的Ajax请求?,javascript,jquery,ajax,asynchronous,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),

我有一个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请求?

来自:将异步选项指定为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
    });
}

极好的解决方案!我注意到,当我试图实现它时,如果我在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;
}

您可以通过调用

jQuery.ajaxSetup({async:false});
然后使用
jQuery.get(…)执行Ajax调用

然后再打开一次

jQuery.ajaxSetup({async:true});

我猜它的工作原理与@Adam所建议的相同,但对于那些确实希望将其
jQuery.get()
jQuery.post()
重新配置为更精细的
jQuery.ajax()的人来说可能会有所帮助
语法。

所有这些答案都忽略了一点,即使用async:false进行Ajax调用将导致浏览器挂起,直到Ajax请求完成。使用流控制库可以在不挂断浏览器的情况下解决此问题。以下是一个示例:

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


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

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

我使用了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;
}

请注意,上述代码仅适用于asyncfalse的情况。如果设置async:true则返回的对象jqxhr在AJAX调用返回时将无效,直到异步调用完成后才有效,但是设置响应变量已经太晚了。

请记住,如果正在进行跨域AJAX调用(使用)-如果不能同步执行,jQuery将忽略
async
标志

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});
对于JSONP调用,您可以使用:

  • Ajax调用您自己的域,并在服务器端执行跨域调用
  • 将代码更改为异步工作
  • 使用类似Frame.js的“函数序列器”库(此)
  • 阻止UI而不是阻止执行(这是我最喜欢的方式)

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

    ES6/ECMAScript 2015 在ES6中,您可以使用发电机&

    ES7 使用ES7,您只需使用asyc Wait:

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

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

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

    Chrome甚至在控制台中警告:

    主线程上的同步XMLHttpRequest不推荐使用,因为它会对最终用户的体验产生有害影响。如需更多帮助,请查看

    这可能会打破你的网页,如果你正在做这样的事情,因为它可能会停止工作的任何一天

    如果您希望以一种仍然感觉是同步的但仍然不阻塞的方式来执行,那么您应该使用async/await,可能还应该使用一些基于新API之类承诺的ajax

    编辑 当用户导航离开或关闭页面时,chrome正在处理。这包括beforeunload、unload、pagehide和visibilitychange

    如果这是您的用例,那么您可能想看一看


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

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

    当我们需要对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
        });
    

    这是我用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();
    

    因为
    xmlhttprepose
    同步操作不受欢迎,所以我提出了以下解决方案来包装
    XMLHttpRequest
    。这允许o
    $.ajax({
      url: url,
      data: data,
      success: success,
      dataType: dataType
    });
    
     $.ajax({
         type: 'GET',
          url: url,
          data: data,
          success: success,
          dataType: dataType,
          async:false
        });
    
    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();
    
    /* 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;
    };
    
    $.get({
      url: url,// mandatory
      data: data,
      success: success,
      dataType: dataType,
      async:false // to make it synchronous
    });