weixin_41568134
MAO-EYE
采纳率0%
2008-09-25 13:26

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

已采纳

I have a JavaScript widget which provides standard extension points. One of them is the beforecreate function. It should return false to prevent an item from being created.

I've added an Ajax call into this function using 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);
  });
}

But I want to prevent my widget from creating the item, so I should return false in the mother-function, not in the callback. Is there a way to perform a synchronous AJAX request using jQuery or any other in-browser API?

转载于:https://stackoverflow.com/questions/133310/how-can-i-get-jquery-to-perform-a-synchronous-rather-than-asynchronous-ajax-re

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

13条回答

  • csdnceshi63 elliott.david 13年前

    From the jQuery documentation: you specify the asynchronous option to be false to get a synchronous Ajax request. Then your callback can set some data before your mother function proceeds.

    Here's what your code would look like if changed as suggested:

    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
        });
    }
    
    点赞 21 评论 复制链接分享
  • csdnceshi76 斗士狗 10年前

    You can put the jQuery's Ajax setup in synchronous mode by calling

    jQuery.ajaxSetup({async:false});
    

    And then perform your Ajax calls using jQuery.get( ... );

    Then just turning it on again once

    jQuery.ajaxSetup({async:true});
    

    I guess it works out the same thing as suggested by @Adam, but it might be helpful to someone that does want to reconfigure their jQuery.get() or jQuery.post() to the more elaborate jQuery.ajax() syntax.

    点赞 30 评论 复制链接分享
  • csdnceshi77 狐狸.fox 11年前

    Excellent solution! I noticed when I tried to implement it that if I returned a value in the success clause, it came back as undefined. I had to store it in a variable and return that variable. This is the method I came up with:

    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;
    }
    
    点赞 24 评论 复制链接分享
  • csdnceshi53 Lotus@ 7年前

    I used the answer given by Carcione and modified it to use 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');
        }    
    }
    

    I added the dataType of 'JSON' and changed the .responseText to responseJSON.

    I also retrieved the status using the statusText property of the returned object. Note, that this is the status of the Ajax response, not whether the JSON is valid.

    The back-end has to return the response in correct (well-formed) JSON, otherwise the returned object will be undefined.

    There are two aspects to consider when answering the original question. One is telling Ajax to perform synchronously (by setting async: false) and the other is returning the response via the calling function's return statement, rather than into a callback function.

    I also tried it with POST and it worked.

    I changed the GET to POST and added data: 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;
    }
    

    Note that the above code only works in the case where async is false. If you were to set async: true the returned object jqxhr would not be valid at the time the AJAX call returns, only later when the asynchronous call has finished, but that is much too late to set the response variable.

    点赞 10 评论 复制链接分享
  • csdnceshi79 python小菜 9年前
    function getURL(url){
        return $.ajax({
            type: "GET",
            url: url,
            cache: false,
            async: false
        }).responseText;
    }
    
    
    //example use
    var msg=getURL("message.php");
    alert(msg);
    
    点赞 8 评论 复制链接分享
  • csdnceshi76 斗士狗 4年前

    Firstly we should understand when we use $.ajax and when we use $.get/$.post

    When we require low level control over the ajax request such as request header settings, caching settings, synchronous settings etc.then we should go for $.ajax.

    $.get/$.post: When we do not require low level control over the ajax request.Only simple get/post the data to the server.It is shorthand of

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

    and hence we can not use other features(sync,cache etc.) with $.get/$.post.

    Hence for low level control(sync,cache,etc.) over ajax request,we should go for $.ajax

     $.ajax({
         type: 'GET',
          url: url,
          data: data,
          success: success,
          dataType: dataType,
          async:false
        });
    
    点赞 6 评论 复制链接分享
  • weixin_41568184 叼花硬汉 7年前

    This is example:

    $.ajax({
      url: "test.html",
      async: false
    }).done(function(data) {
       // Todo something..
    }).fail(function(xhr)  {
       // Todo something..
    });
    
    点赞 6 评论 复制链接分享
  • csdnceshi70 笑故挽风 9年前

    All of these answers miss the point that doing an Ajax call with async:false will cause the browser to hang until the Ajax request completes. Using a flow control library will solve this problem without hanging up the browser. Here is an example with 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();
    }
    
    点赞 5 评论 复制链接分享
  • csdnceshi73 喵-见缝插针 5年前

    Note: You shouldn't use async due to this:

    Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.

    Chrome even warns about this in the console:

    Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

    This could break your page if you are doing something like this since it could stop working any day.

    If you want to do it a way that still feels like if it's synchronous but still don't block then you should use async/await and probably also some ajax that is based on promises like the new Fetch API

    async function foo() {
      var res = await fetch(url)
      console.log(res.ok)
      var json = await res.json()
      console.log(json)
    }
    
    点赞 5 评论 复制链接分享
  • csdnceshi60 ℡Wang Yan 5年前

    With async: false you get yourself a blocked browser. For a non blocking synchronous solution you can use the following:

    ES6/ECMAScript2015

    With ES6 you can use a generator & the 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

    With ES7 you can just use 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
        })(); 
    }
    
    点赞 5 评论 复制链接分享
  • csdnceshi75 衫裤跑路 6年前

    Keep in mind that if you're doing a cross-domain Ajax call (by using JSONP) - you can't do it synchronously, the async flag will be ignored by jQuery.

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

    For JSONP-calls you could use:

    1. Ajax-call to your own domain - and do the cross-domain call server-side
    2. Change your code to work asynchronously
    3. Use a "function sequencer" library like Frame.js (this answer)
    4. Block the UI instead of blocking the execution (this answer) (my favourite way)
    点赞 2 评论 复制链接分享
  • csdnceshi55 ~Onlooker 3年前

    Because XMLHttpReponse synchronous operation is deprecated I came up with the following solution that wraps XMLHttpRequest. This allows ordered AJAX queries while still being asycnronous in nature, which is very useful for single use CSRF tokens.

    It is also transparent so libraries such as jQuery will operate seamlessly.

    /* 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;
    };
    
    点赞 评论 复制链接分享
  • csdnceshi76 斗士狗 3年前

    this is my simple implementation for ASYNC requests with jQuery. I hope this help anyone.

    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();
    
    点赞 评论 复制链接分享